Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python dictionary passed as an input to a function acts like a global in that function rather than a local

I am very confused by the behaviour below. Cases 1, 3, and 4 perform as I would expect, but case 2 does not. Why does case 2 allow the function to change the value of the dictionary entry globally, even though the dictionary is never returned by the function? A main reason I am using functions is to isolate everything in the function from the rest of the code, but this does not seem to be possible if I choose to use the same variable names inside of the function. I was under the understanding that anything explicitly defined in a function is local to that function, but this does not seem to be the case if the dictionary is defined and passed as an input to the function.

Python 2.7.2+ (default, Oct  4 2011, 20:06:09)  [GCC 4.6.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. 

=============Case 1===============

>>> def testfun1(a): ...     a=2 ...  >>> a=0 >>> testfun1(a) >>> a 0 

=============Case 2===============

>>> def testfun2(b): ...     b['test']=2 ...  >>> b={} >>> testfun2(b) >>> b {'test': 2} 

=============Case 3===============

>>> def testfun3(): ...     c=2 ...  >>> c=0 >>> testfun3() >>> c 0 

=============Case 4=============== (explained by this question: Global dictionaries don't need keyword global to modify them?)

>>> def testfun4(): ...     d['test']=10 ...  >>> d={} >>> testfun4() >>> d {'test': 10} 
like image 534
user1748155 Avatar asked Feb 25 '13 23:02

user1748155


People also ask

Can a dictionary be global in Python?

Use the global keyword in the dictionary when you want to change the value in Python. If the dictionary is defined outside function then by default it has global scope.

Can you pass a dictionary to a function?

Passing Dictionary as an argument In Python, everything is an object, so the dictionary can be passed as an argument to a function like other variables are passed.

Is dictionary passed by reference in Python?

In essence, one can say that mutable objects like dictionaries, sets, and lists are passed by reference. Immutable objects like int , str , tuple are passed by value.


2 Answers

Python's "parameter evaluation strategy" acts a bit different than the languages you're probably used to. Instead of having explicit call by value and call by reference semantics, python has call by sharing. You are essentially always passing the object itself, and the object's mutability determines whether or not it can be modified. Lists and Dicts are mutable objects. Numbers, Strings, and Tuples are not.

You are passing the dictionary to the function, not a copy. Thus when you modify it, you are also modifying the original copy.

To avoid this, you should first copy the dictionary before calling the function, or from within the function (passing the dictionary to the dict function should do it, i.e. testfun4(dict(d)) and defining the function as def testfun4(d):).

like image 63
Casey Kuball Avatar answered Oct 12 '22 23:10

Casey Kuball


To support what @Casey Kuball said, every object in Python is passed by reference. Each function receives a reference to the actual object you passed. Modifying these objects depends on whether they are mutable data types.

In essence, one can say that mutable objects like dictionaries, sets, and lists are passed by reference. Immutable objects like int, str, tuple are passed by value.

You should also note that there are cases where mutable objects are overwritten in a function thereby losing reference to the actual object passed to the function.

>>> def testfun(b): ...     b = b or {}  # Creates a new object if b is false ...     b['test'] = 2 ...  >>> b = {} >>> testfun(b) >>> b {} 
like image 42
Chuma Umenze Avatar answered Oct 12 '22 22:10

Chuma Umenze