您应该知道,使用is或id的测试可能会误导您,是否使用不可变和interned对象(如包含不可变的字符串、整数和元组)生成了真正的副本。
考虑一个容易理解的例子:>>> l1=['one']
>>> l2=['one']
>>> l1 is l2
False
>>> l1[0] is l2[0]
True
现在制作l1的浅拷贝并测试不可变字符串:>>> l3=l1[:]
>>> l3 is l1
False
>>> l3[0] is l1[0]
True
现在复制l1[0]包含的字符串:>>> s1=l1[0][:]
>>> s1
'one'
>>> s1 is l1[0] is l2[0] is l3[0]
True # they are all the same object
尝试deepcopy,在其中复制每个元素:>>> from copy import deepcopy
>>> l4=deepcopy(l1)
>>> l4[0] is l1[0]
True
在每种情况下,字符串'one'都被存放在Python的不可变字符串的内部缓存中,并且is将显示它们是相同的(它们具有相同的id)。它的实现和版本取决于什么时候实习,什么时候实习,所以你不能依赖它。它可以极大地提高内存和性能。
你可以强迫一个不能立即实习的例子:>>> s2=''.join(c for c in 'one')
>>> s2==l1[0]
True
>>> s2 is l1[0]
False
然后可以使用Pythonintern function使该字符串引用找到的缓存对象:>>> l1[0] is s2
False
>>> s2=intern(s2)
>>> l1[0] is s2
True
同样适用于不可变元组:>>> t1=('one','two')
>>> t2=t1[:]
>>> t1 is t2
True
>>> t3=deepcopy(t1)
>>> t3 is t2 is t1
True
可变的不可变列表(如整数)可以将列表成员插入:>>> li1=[1,2,3]
>>> li2=deepcopy(li1)
>>> li2 == li1
True
>>> li2 is li1
False
>>> li1[0] is li2[0]
True
因此,您可以使用python操作,您知道这些操作将复制某些内容,但最终结果是对一个内部不可变对象的另一个引用。如果项是可变的,则is测试只是对正在生成的副本的处理测试。