Python中的元组和列表对象

5

有人能为我解释一下这个吗?

>>> [] is []
False
>>> () is ()
True
>>> (1,) is (1,)
False

我知道在比较值时应该使用 "==" 而不是 "is",但我想知道为什么要这样做?

3个回答

10

is 基于对象标识。也就是说,左右两边是否为同一对象?

在所有这些情况中,这些对象通常是不同的(因为您有六个单独的文字)。然而,空元组由于实现相关的内部化而是相同的对象。正如您所指出的,您永远不应该依赖此行为。

请注意,可变对象无法进行内部化,因此第一个条件必须为假。


2
请注意,“interning”通常适用于字符串以及任何其他不可变的文字/值。因为它们是不可变的,Python的任何实现都可以选择使不同的引用汇聚(指向)任何单个对象实例。这就是在此上下文中“interning”的含义。Interning是一种针对常见用例进行优化的实现细节。顺便说一句,Python列表是可变的,因此不能被interning所影响。 - Jim Dennis
1
第一个不是列表和元组之间的比较,而是两个列表之间的比较。这是错误的,因为它们是不同的对象(即具有不同的ID),只是恰好具有相同的值(即都是空列表)。 - rbp

3

在比较id时要小心,如果一个对象被垃圾回收,那么它的id可能会被重用!

>>> id([])==id([])
True

甚至甚至
>>> id([1,2,3])==id(["A","B","C"])
True

2
这样来想:对于像元组这样的不可变对象,在Python实现中,如果它们是相同的,共享它们是安全的。
>>> a = ()
>>> b = ()
>>> a is b
True

现在考虑以下内容:
>>> a = []
>>> b = []
>>> a.append("foo")
>>> print a,b
['foo'] []

因为修改a不应该修改b,所以a和b不能是同一个对象。

在你的最终示例中,你又回到了不可变的元组。Python实现允许将它们设置为同一个对象,但并不要求这样做,在这种情况下它没有这样做(这基本上是一种时间/空间的权衡 - 如果你在程序中使用了大量的(1,),如果它们被整合,可以节省内存,但确定任何给定的元组是否是可以共享对象的(1,)会消耗运行时间)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接