"is" Python 运算符是否可以可靠地测试可变对象的引用相等性?

Is the "is" Python operator reliable to test reference equality of mutable objects?

我知道 Python 中的 is 运算符对整数和字符串等不可变对象有意外行为。参见 "is" operator behaves unexpectedly with integers

>>> a = 0
>>> b = 0
>>> a is b
True        # Unexpected, we assigned b independently from a

当谈到 可变对象 时,我们是否保证预期(如代码中所写)引用两个不同对象(具有相等值)的两个变量不会是内部绑定到同一个对象? (除非我们改变两个变量之一,否则引用当然会有所不同。)

>>> a = [0]
>>> b = [0]
>>> a is b
# Is False guaranteed ?

换句话说,如果某处 x is y returns Truexy 是可变对象),我们是否保证变异 x 也会变异 y ?

只要您认为某些“是”行为是“意外”的,您的心智模型就与现实不符;-)

您的问题 确实 关于 Python 何时保证创建新对象。而当它没有时。对于可变对象,是的,产生可变对象的构造函数(包括文字)总是创建一个新对象。这就是为什么:

>>> a = [0]
>>> b = [0]
>>> a is b

总是 False。 Python 可以 说过 [0] 的每个实例是否创建一个新对象是未定义的,但它没有:它保证每个实例总是创建一个新对象. is 行为是结果,而不是驱动因素。

同样,

>>> a = set()
>>> b = set()
>>> a is b
False

也有保障。因为 set() return 是一个可变对象,它总是保证创建一个新的此类对象。

但对于不可变对象,未定义。比如这个结果没有定义:

>>> a = frozenset()
>>> b = frozenset()
>>> a is b

frozenset() - 就像整数文字 - return 是一个不可变的对象,它取决于实现是 return 一个新对象还是重用现有对象。在这个具体的例子中,a is bTrue,因为今天的实现 碰巧 重用一个空的 frozenset。但是,例如,碰巧

>>> a = frozenset([3])
>>> b = frozenset([3])
>>> a is b
False

今天。它也可以 return True 明天(尽管这不太可能 - 虽然空的 frozenset 是一种易于检测的特殊情况,但确保所有 frozenset 对象的唯一性会很昂贵)。