Why do python lists act like this when using the = operator
为什么会出现以下代码:
1 2 3 4 | a = [1,2,3] b = a b[0] = 3 print(a) |
B表修改后会打印吗?[3,2,3]。这也是为什么是真的,但是下面的代码:
1 2 3 4 | a = [1,2,3] b = a b = [0,0,0] print(a,b) |
打印[1,2,3][0,0,0]??这似乎不一致。如果第一个代码为真,那么第二个代码不应该打印[0,0,0][0,0,0]?有人能解释一下吗?
在python中有两种类型的数据…可变的和不变的。数字、字符串、布尔值、元组和其他简单类型是不可变的。字典、列表、集合、对象、类和其他复杂类型是可变的。
当你说:
1 2 | a = [1,2,3] b = a |
您在内存中创建了一个单一的可变列表,将
因此,当你改变它(修改它)时:
1 | b[0] = 3 |
它是
但是,当您更换它时:
1 | b = [0,0,0] |
它正在内存中创建一个新的可变列表,并指定
查看
奖励:python中的每个值都是通过引用传递的…也就是说,当您将它赋给一个变量时,它只会使该变量指向它在内存中的那个值。拥有不可变类型允许Python"重用"相同的内存位置来处理常见的不可变类型。
在解释器启动时考虑一些常见的值:
1 2 3 4 5 6 7 | >>> import sys >>> sys.getrefcount('abc') 68 >>> sys.getrefcount(100) 110 >>> sys.getrefcount(2) 6471 |
然而,一个绝对不存在的值将返回
1 2 | >>> sys.getrefcount('nope not me. I am definitely not here already.') 2 |
注意,空元组有很多引用:
1 2 | >>> sys.getrefcount(tuple()) 34571 |
但是空列表没有额外的引用:
1 2 | >>> sys.getrefcount(list()) 1 |
为什么会这样?因为元组是不可变的,所以可以跨任意数量的变量共享该值。但是,列表是可变的,因此不能在任意变量之间共享,或者对其中一个的更改会影响其他变量。
顺便说一句,这也是为什么您不能使用可变类型作为函数的默认参数值的原因。想想这个天真的小功能:
1 2 3 4 5 | >>> def foo(value=[]): ... value.append(1) ... print(value) ... ... |
当你打电话给它的时候,你可能会期望得到
1 2 | >>> foo() [1] |
但是,当你再次调用它时,你会探测。不会指望把
1 2 | >>> foo() [1, 1] |
一天又一天…
1 2 3 4 5 | >>> foo() [1, 1, 1] >>> foo() [1, 1, 1, 1] |
为什么会这样?因为函数的默认参数在函数定义期间只计算一次,而不是在函数运行时。这样,如果您使用可变值作为默认参数值,那么您将一直使用该值,在函数被多次调用时以意外的方式发生变化。
正确的方法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> def foo(value=None): ... if value is None: ... value = [] ... value.append(1) ... print(value) ... ... >>> >>> foo() [1] >>> foo() [1] >>> foo() [1] |