我注意到一个(看似)奇怪的分配行为,这让我多次犯了编程错误。
首先参见以下示例:
>>> i = 0
>>> t = (i,)
>>> t
(0,)
>>> i += 1
>>> t
(0,)
正如预期的那样,t
的唯一元素的值即使在i
的值增加后也不会改变。
现在查看以下内容:
>>> l = [0]
>>> t = (l,)
>>> t
([0],)
>>> l[0] += 1
>>> t
([1],) # <- ?
我不明白为什么t
中的初始零现在是一个;如果我通过引用t
...
>>> t[0][0] += 1
...我知道它的值已经改变了,但在前面的例子中并非如此,其中只有l
在递增时被显式引用。
我有两个问题:
答案 0 :(得分:8)
那是因为整数是不可变的,列表是可变的。
>>> i = 0
>>> t = (i,)
>>> t[0] is i # both of them point to the same immutable object
True
>>> i += 1 # We can't modify an immutable object, changing `i` simply
# makes it point to a new object 2.
# All other references to the original object(0) are still intact.
>>> i
1
>>> t # t still points to the same 0
(0,)
>>> x = y = 1
>>> id(x),id(y)
(137793280, 137793280)
>>> x += 1
>>> id(x),id(y) #y still points to the same object
(137793296, 137793280)
列表:
>>> l = [0]
>>> t = (l,)
>>> t[0] is l #both t[0] and l point to the same object [0]
True
>>> l[0] += 1 # modify [0] in-place
>>> t
([1],)
>>> l
[1]
#another exmple
>>> x = y =[] # x, y point to the same object
>>> x.append(1) # list.append modifies the list in-place
>>> x, y
([1], [1])
>>> x = x + [2] # only changes x, x now points to a new object
>>> x, y
([1, 2], [1])
答案 1 :(得分:2)
在第二个示例中,t
(元组)包含对l
(列表)的引用。执行l[0] += 1
时,您正在更改列表,但元组仍保留对列表的引用。在第一个示例中,当您执行i += 1
时,您实际上正在创建一个新整数,您的元组不会对其进行引用。请参阅我之前写过的this answer,以便对+=
运算符及其实际实现方式进行更深入的解释。