对于不可变的数据类型,Python不保证两个构造会产生两个不同的对象;因此1+1 is 2
可以返回True
,也可以不返回。当然,可变的类型do会导致单独的对象:[] is []
将始终返回False
。
发件人https://docs.python.org/3/reference/datamodel.html#objects-值和类型:
类型几乎影响对象行为的所有方面。甚至对象标识的重要性也在某种意义上受到了影响:对于不可变类型,计算新值的操作实际上可能会返回对任何具有相同类型和值的现有对象的引用,而对于可变对象,这是不允许的。例如,在a=1之后;b=1,a和b可能引用或不引用值为1的同一对象,具体取决于实现,但在c=[]之后;d=[],c和d保证引用两个不同的、唯一的、新创建的空列表。(注意,c=d=[]为c和d分配相同的对象。(
>>> "abc" is "abc"
True
>>> [] is []
False
>>> 1 + 1 is 2
True
现在,除了琐碎的类型int
、float
、bool
、string
之外,我希望tuple
和frozenset
表现出相同的行为。
但我没有发现他们这样做的案例:
>>> {1, 2} is {1, 2}
False
>>> (1, ) is (1, )
False
是否有任何实现为单独的不可变对象生成相同的id?
这些对象的所有is
等式都是由解释器技巧产生的(这不是语言规范AFAIK的一部分,而是CPython的结果(
例如(使用int
(。
当前实现为-5到256之间的所有整数保留一个整数对象数组,当您在该范围内创建一个int时,实际上只会返回对现有对象的引用。
因此应该可以更改1的值。我怀疑Python在这种情况下的行为是未定义的。:-(
对于字符串,python执行interning
。bool
是int
(issubclass(bool, int)
(的一个子类,它解释了bool
的共享id
。AFAIK,对于is
相等,浮点(除了3.8中的文字(永远不会返回True。
在python3.8中,由于文字评估的变化,(1,) is (1,)
实际上是True
。
>>> (1,) is (1,)
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
同时对用于文字的is
发出警告。但是,分配变量并执行比较是False(正如预期的那样(。
请注意,tuple() is tuple()
和frozenset() is frozenset()
都返回True。然而,它们的可变对应物(list
和set
(不具有此属性。