关于不变性:python引用

Python references

有人能解释为什么带整数的例子会导致x和y的值不同,而带列表的例子会导致x和y是同一个对象吗?

1
2
3
4
5
6
7
8
9
10
11
12
x = 42
y = x
x = x + 1
print x # 43
print y # 42

x = [ 1, 2, 3 ]
y = x
x[0] = 4
print x # [4, 2, 3]
print y # [4, 2, 3]
x is y # True


我读过的最好的解释是:http://python.net/~goodger/projects/pycon/2007/惯用/讲义.html其他语言有变量


因为整数是不可变的,而列表是可变的。从语法中可以看到。在x = x + 1中,您实际上为x分配了一个新值(仅在lhs上)。在x[0] = 4中,您调用列表上的index操作符并给它一个参数—它实际上相当于x.__setitem__(0, 4),这显然改变了原始对象,而不是创建新对象。


如果执行y = x,则y和x是对同一对象的引用。但是整数是不可变的,当您执行x + 1操作时,将创建新的整数:

1
2
3
4
5
6
7
8
9
>>> x = 1
>>> id(x)
135720760
>>> x += 1
>>> id(x)
135720748
>>> x -= 1
>>> id(x)
135720760

当你有一个可变的对象(例如列表,你自己定义的类)时,每当y改变时,x就会改变,因为它们指向一个单一的对象。


正如前面的答案所说,您编写的代码将相同的对象分配给不同的名称,例如别名。如果要将原始列表的副本分配给新变量(实际上是对象)使用此解决方案:

1
2
3
4
5
6
7
8
9
10
11
>>> x=[1,2,3]
>>> y=x[:] #this makes a new list
>>> x
[1, 2, 3]
>>> y
[1, 2, 3]
>>> x[0]=4
>>> x
[4, 2, 3]
>>> y
[1, 2, 3]

这是因为当您在Python中有一个列表或元组时,您将创建一个对对象的引用。当你说y=x时,你引用的是与x相同的带有y的对象。所以当你编辑x y的对象时,它会随之改变。