所以我得到了以下代码:
def foo(a, b, c):
try:
a = [0]
b[0] = 1
c[0] = 2
w[0] = 3
except:
pass
return z
x, y, z = [None], [None], [None]
w = z[:]
foo(x,y,z)
print(x,y,z,w)print(x,y,z,w)代码的最后一行打印[None] [1] [2] [3],但是我不太明白。为什么x,y,z在功能上被改变了?如果w改变了--它指向了z,为什么z不相应地改变呢?
发布于 2019-06-15 17:20:33
在Python中,对象通过引用函数传递。此行生成z的副本
w = z[:]因此,对z的更改不会影响w,反之亦然。排在队伍里
a = [0]将引用更改为指向一个新对象,这样就不会更改x (这是a最初绑定的对象)。在以下几行
b[0] = 1
c[0] = 2您更改了引用的对象(全局范围中的y和z ),因此外部作用域中的对象发生了变化。排在队伍里
w[0] = 3您可以变异全局对象w,因为名称w不是函数的参数,也不绑定到函数的正文中。
发布于 2019-06-15 17:45:08
其他人说的都是正确的,但我想补充一下,如果您有使用C或C++这样的语言的经验,我的思维方式可能会有所帮助。
中的每个变量都是指针(技术术语是“引用”,但我发现这比“指针”更难可视化)。您知道在C/C++中如何通过传递指针来获得输出多个值的函数吗?您的代码基本上是在做相同的事情。
当然,您可能想知道,如果是这样的话,为什么您没有看到ints、strs或诸如此类的事情发生呢?原因是这些东西是不可变的,这意味着您根本无法直接更改int或str的值。当您“更改一个整数”(如i = 1 )时,您实际上是在更改变量,将其指向另一个int对象。类似地,s += 'abc'使用值s + 'abc'创建一个新的str对象,然后将其分配给s。(这就是为什么当s += 'abc'很长时,s可能效率很低,而不是附加到列表中!)
注意,当您执行a = [0]时,您正在以第二种方式更改a --更改指针而不是指向的对象。这就是为什么这一行不修改x的原因。
最后,正如其他人所说的,w = z[:]复制了一份。这可能有点令人困惑,因为对于其他一些对象(如numpy数组),这个语法生成一个视图而不是一个副本,这意味着在更改元素时,它的作用类似于同一个对象。请记住,[]只是一个运算符,每种类型的对象都可以选择赋予它不同的语义意义。就像%是int的模式,str的格式一样--有时候你只需要熟悉不同类型的特性。
https://stackoverflow.com/questions/56612509
复制相似问题