作为输入传递给函数的python字典在该函数中充当全局而不是局部
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15078519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
python dictionary passed as an input to a function acts like a global in that function rather than a local
提问by user1748155
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.
我对下面的行为感到非常困惑。案例 1、3 和 4 的表现符合我的预期,但案例 2 则不然。为什么情况 2 允许函数全局更改字典条目的值,即使函数从不返回字典?我使用函数的一个主要原因是将函数中的所有内容与代码的其余部分隔离开来,但是如果我选择在函数内部使用相同的变量名,这似乎是不可能的。我的理解是,在函数中明确定义的任何内容都是该函数的本地内容,但如果字典被定义并作为输入传递给函数,情况似乎并非如此。
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===============
==============案例1================
>>> def testfun1(a):
... a=2
...
>>> a=0
>>> testfun1(a)
>>> a
0
=============Case 2===============
==============案例2================
>>> def testfun2(b):
... b['test']=2
...
>>> b={}
>>> testfun2(b)
>>> b
{'test': 2}
=============Case 3===============
==============案例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?)
==============案例4================(由这个问题解释:全局字典不需要关键字global来修改它们?)
>>> def testfun4():
... d['test']=10
...
>>> d={}
>>> testfun4()
>>> d
{'test': 10}
采纳答案by Casey Kuball
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.
Python 的参数传递行为与您可能习惯的语言略有不同。python 没有显式按值传递和按引用传递语义,而是按名称传递。你本质上总是传递对象本身,对象的可变性决定了它是否可以被修改。列表和字典是可变对象。数字、字符串和元组不是。
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 dictfunction should do it).
为避免这种情况,您应该在调用函数之前或从函数内部复制字典(将字典传递给dict函数应该这样做)。
回答by Demian Brecht
The global keyword is required only for assignment (and likely del, I've never tried it). Object mutations are perfectly valid.
global 关键字仅用于赋值(很可能del,我从未尝试过)。对象突变是完全有效的。
回答by wRAR
You have passed a dictobject 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.
你已经dict给函数传递了一个对象,并在函数内部修改了它,所以当然会在函数返回后被修改。对象不会被复制,所以你修改了你传递的同一个对象,这个问题与你显式传递对象时的命名、相似名称、范围等无关。
回答by sissi_luaty
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.
当您将整数或字符串等基本对象传递给函数时,如果您在函数内部更改它,则函数外部的相应对象不会发生任何变化,因为当您以基本对象开头时,python 按值传递它。
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.
编辑:另外,按值传递和按引用传递是有区别的:按值传递,是对对象进行“拷贝”,以便在函数中使用;通过引用,完全相同的对象通过引用传递,并且在函数内部对其进行的修改在外部可见。根据定义,python 通过值传递其不可变对象,并通过引用传递其可变对象。
回答by Chuma Umenze
To support what @Casey Kuballsaid, 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.
为了支持@Casey Kuball所说的,Python 中的每个对象都是通过引用传递的。每个函数都会收到对您传递的实际对象的引用。修改这些对象取决于它们是否是可变数据类型。
In essence, one can say that mutable objects like dictionaries, sets, and lists are passed by reference. Immutable objects like int, str, tupleare passed by value.
本质上,可以说像字典、集合和列表这样的可变对象是通过引用传递的。不可变对象,如int,str,tuple是按值传递。
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
{}

