当变量类型(int、float、list、dict、string等(的值相同时,它们会采用相同的地址。
a1, b1 = 1, 1 #int
a2, b2 = 1.1, 1.1 #float
a3, b3 = 1j, 1j #complex
a4, b4 = [1, 2], [1, 2] #list
a5, b5 = (1, 2), (1, 2) #tuple
a6, b6 = range(10), range(10) #range
a7, b7 = {"a": 1, "b": 2}, {"a": 1, "b": 2} #dict
a8, b8 = {1, 2}, {1, 2} #set
a9, b9 = frozenset({1, 2}), frozenset({1, 2}) #frozenset
a10, b10 = True, True #bool
a11, b11 = b"aa", b"aa" #bytes
a12, b12 = bytearray((1, 2)), bytearray((1, 2)) #bytearray
对于任何类型的变量(布尔值除外(,这都不是一个安全的假设。
通常,这种行为被称为";实习简单的不可变值被存储和缓存,以节省一点内存。正如这个答案中所阐述的,小整数和字符串通常被嵌入,但并不总是,依赖这种行为会导致一些难以调试的错误。
int
和str
,特别是空元组()
,是我观察到的唯一表现出这种行为的类型,即使在那时,它们何时停止也是不可预测的。
对于大多数其他简单的不可变类型(int
、float
、complex
、tuple
、bool
、bytes
(,您可以相互比较文字,解释器会在发出警告后告诉您True
,但将它们分配给变量并重复检查会产生False
:
>>> (1, 2) is (1, 2)
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
>>> a = (1, 2)
>>> b = (1, 2)
>>> a is b
False
可变或复杂类型(range
、list
、dict
、set
、frozenset
、bytearray
(将永远不会占用彼此相同的内存,即使相同,因此即使与文字进行is
比较也会返回false:
>>> bytearray((1, 2)) is bytearray((1, 2))
False
显然,任何两种不同的类型在is
比较中都不会返回true
。
布尔和None
是一种特殊情况。它们被定义为全局常量,事实上,True
和False
的每次调用都明确指向内存中相同的两个实例。您可以安全地使用is
来比较任何两个布尔值。
当您想要消除可能是True
、False
或None
的值之间的歧义时,这实际上很有用。简单地检查真实性(if not condition:
(会将False
和None
分组在一起,因此您可能需要检查if condition is False:
以明确排除None
。