参考或复制

时间:2011-08-08 11:31:06

标签: python python-3.x

我刚开始使用Python 3.在Python书中,我读到可以强制解释器创建实例的副本,而不是使用切片符号创建引用。

这应该创建对s1的现有实例的引用:

s1 = "Test"
s2 = s1
print(s1 == s2)
print(s1 is s2)

这应该创建一个新实例:

s1 = "Test"
s2 = s1[:]
print(s1 == s2)
print(s1 is s2)

运行上面的示例时,两者都返回相同的结果,即对s1的引用。 sombody可以解释为什么它不像书中描述的那样工作?这是我的错误,还是书中的错误?

4 个答案:

答案 0 :(得分:7)

对于可变数据类型(如列表)也是如此(即按照您期望的s1 = [1,2,3]工作)。

但是字符串也是例如python中的元组是不可变的(意味着它们无法更改,您只能创建新实例)。 python解释器没有理由创建这样的对象的副本,因为你不能通过s1影响s2,反之亦然,你只能让s1或s2指向不同的字符串。

答案 1 :(得分:2)

由于字符串是不可变的,因此字符串的副本和字符串的新引用之间没有很大的区别。创建列表副本的能力很重要,因为列表是可变的,您可能希望更改一个列表而不更改另一个列表。但是改变字符串是不可能的,因此制作副本无法获得任何好处。

答案 2 :(得分:2)

字符串在Python中是不可变的。这意味着,一旦创建了一个字符串并将其写入内存,就无法对其进行修改。每次“修改”字符串时,都会创建一个新副本 你可能会注意到CPython的另一个有趣的行为:

s1 = 'Test'
s2 = 'Test'
id(s1) == id(s2)
>>> True

如您所见,在CPython中,s1和s2在内存中引用相同的地址。

如果您需要可变对象的完整副本(例如列表),请检查标准库中的copy模块。 E.g。

import copy

l1 = [1,2,3]
l2 = l1
id(l2) == id(l1) # a reference
>>> True

l3 = copy.deepcopy(l1)
id(l3) == id(l1)
>>> False     

答案 3 :(得分:1)

只有当对象应用于列表时,切片副本才会为您提供对象的新副本:

>>> t = ()
>>> t is t[:]
True
>>> l = []
>>> l is l[:]
False
>>> s = ''
>>> s is s[:]
True

已经在python-dev mailing list中讨论了使用字符串进行切片复制工作的方法,但该功能因性能问题而被拒绝。