我正在尝试理解Python的变量范围方法.在这个例子中,为什么f()
能够改变x
内部感知main()
的价值,而不是价值n
?
def f(n, x): n = 2 x.append(4) print('In f():', n, x) def main(): n = 1 x = [0,1,2,3] print('Before:', n, x) f(n, x) print('After: ', n, x) main()
输出:
Before: 1 [0, 1, 2, 3] In f(): 2 [0, 1, 2, 3, 4] After: 1 [0, 1, 2, 3, 4]
jfs.. 195
某些答案在函数调用的上下文中包含单词"copy".我觉得很困惑.
Python不复制的对象,你的函数调用中传递过.
函数参数是名称.当您调用函数时,Python会将这些参数绑定到您传递的任何对象(通过调用方范围中的名称).
对象可以是可变的(如列表)或不可变的(如Python中的整数,字符串).你可以改变的可变对象.您无法更改名称,只需将其绑定到另一个对象即可.
您的示例不是关于范围或命名空间,而是关于Python中对象的命名和绑定以及可变性.
def f(n, x): # these `n`, `x` have nothing to do with `n` and `x` from main() n = 2 # put `n` label on `2` balloon x.append(4) # call `append` method of whatever object `x` is referring to. print('In f():', n, x) x = [] # put `x` label on `[]` ballon # x = [] has no effect on the original list that is passed into the function
以下是关于其他语言中的变量与Python中的名称之间差异的精彩图片.
某些答案在函数调用的上下文中包含单词"copy".我觉得很困惑.
Python不复制的对象,你的函数调用中传递过.
函数参数是名称.当您调用函数时,Python会将这些参数绑定到您传递的任何对象(通过调用方范围中的名称).
对象可以是可变的(如列表)或不可变的(如Python中的整数,字符串).你可以改变的可变对象.您无法更改名称,只需将其绑定到另一个对象即可.
您的示例不是关于范围或命名空间,而是关于Python中对象的命名和绑定以及可变性.
def f(n, x): # these `n`, `x` have nothing to do with `n` and `x` from main() n = 2 # put `n` label on `2` balloon x.append(4) # call `append` method of whatever object `x` is referring to. print('In f():', n, x) x = [] # put `x` label on `[]` ballon # x = [] has no effect on the original list that is passed into the function
以下是关于其他语言中的变量与Python中的名称之间差异的精彩图片.
你已经有了很多答案,我对JF Sebastian大致赞同,但你可能会发现这个有用的快捷方式:
无论何时varname =
,您都会在函数范围内创建新的名称绑定.无论varname
以前绑定的价值在这个范围内都会丢失.
任何时候你看到varname.foo()
你正在调用方法varname
.该方法可以改变varname(例如list.append
). varname
(或者说,varname
名称对象)可能存在于多个范围内,并且由于它是同一个对象,因此任何更改都将在所有范围内可见.
[请注意,global
关键字会为第一个案例创建例外]
f
实际上并没有改变x
(它始终与列表实例的引用相同)的值.相反,它改变了这个列表的内容.
在这两种情况下,都会将引用的副本传递给函数.在功能里面,
n
获得一个新的值.仅修改函数内部的引用,而不修改函数内部的引用.
x
不会为其分配新值:既不修改函数内部的引用,也不修改函数外部的引用.相反,它x
的价值被修改了.
由于x
函数内部和外部都引用相同的值,因此都看到修改.相比之下,n
函数内部和外部它在函数内部重新分配后引用不同的值n
.
我将重命名变量以减少混乱。 n- > nf或nmain。 x- > xf或xmain:
def f(nf, xf): nf = 2 xf.append(4) print 'In f():', nf, xf def main(): nmain = 1 xmain = [0,1,2,3] print 'Before:', nmain, xmain f(nmain, xmain) print 'After: ', nmain, xmain main()
当调用函数f时,Python运行时将复制xmain并将其分配给xf,同样,将nmain的副本分配 给nf。
In the case of n, the value that is copied is 1.
In the case of x the value that is copied is not the literal list [0, 1, 2, 3]. It is a reference to that list. xf and xmain are pointing at the same list, so when you modify xf you are also modifying xmain.
If, however, you were to write something like:
xf = ["foo", "bar"] xf.append(4)
您会发现xmain尚未更改。这是因为在xf = [“ foo”,“ bar”]行中,您已更改xf指向新列表。您对此新列表所做的任何更改都不会影响xmain仍指向的列表。
希望能有所帮助。:-)