python dictionary passed as an input to a function

2019-01-31 16:51发布

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}

4条回答
淡お忘
2楼-- · 2019-01-31 17:26

Python's parameter passing acts a bit different than the languages you're probably used to. Instead of having explicit pass by value and pass by reference semantics, python has pass by name. 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).

查看更多
我只想做你的唯一
3楼-- · 2019-01-31 17:31

The global keyword is required only for assignment (and likely del, I've never tried it). Object mutations are perfectly valid.

查看更多
\"骚年 ilove
4楼-- · 2019-01-31 17:41

When you pass a basic object like an integer or a string to a function, if you change it inside the function nothing occurs to the corresponding object outside the function because when you are leading with a basic object, python passes it by value.

However, if you pass a dictionary or a list to a function they are passed by reference, which means you will have that behaviour: the object outside the function is changed, as you have seen.

edit: In addition, there is a difference between passing by value or by reference: by value, a "copy" of the object is made in order to be used in the function; by reference, the exactly same object is passed through reference and modifications to it inside the function are visible outside. By definition python passes its immutable objects by value, and its mutable objects by reference.

查看更多
干净又极端
5楼-- · 2019-01-31 17:43

You have passed a dict object to the function and modified it inside the function, so of course it will be modified after the function return. The object is not copied so you modify the same object that you passed, and this question has nothing to do with naming, similar names, scopes etc. as you passed the object explicitly.

查看更多
登录 后发表回答