"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 True
(x
和 y
是可变对象),我们是否保证变异 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 b
是 True
,因为今天的实现 碰巧 重用一个空的 frozenset。但是,例如,碰巧
>>> a = frozenset([3])
>>> b = frozenset([3])
>>> a is b
False
今天。它也可以 return True
明天(尽管这不太可能 - 虽然空的 frozenset 是一种易于检测的特殊情况,但确保所有 frozenset 对象的唯一性会很昂贵)。
我知道 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 True
(x
和 y
是可变对象),我们是否保证变异 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 b
是 True
,因为今天的实现 碰巧 重用一个空的 frozenset。但是,例如,碰巧
>>> a = frozenset([3])
>>> b = frozenset([3])
>>> a is b
False
今天。它也可以 return True
明天(尽管这不太可能 - 虽然空的 frozenset 是一种易于检测的特殊情况,但确保所有 frozenset 对象的唯一性会很昂贵)。