在 python 中,有个 id() 函数,是用来获得一个 Object 的 id 的,在文档中介绍也非常简单:
id(object)
Return the “ identity ” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.
这是 python 为每个 Object 在运行时定制了一个唯一 id,但是需要注意的是,当两个 Object 当生命域不重叠的时候,可能会有相同的 id。
Object's Identity
对于任何一个 Object 来说,都有一个 id,如果多个变量指向了同一个静态常量,那么这几个变量讲拥有同样的 id。
>>> s1 = "abc"
>>> s2 = "abc"
>>> s1 == s2
True
>>> id(s1)
4390873208
>>> id(s2)
4390873208
>>> s1 is s2
True
如果两个不同的变量(常量),肯定将有不同的 id。
>>> id("abc")
4390873208
>>> id("abcd")
4391753216
is 比较
在 python 中,有两种常用的比较方式,一个是 ==
比较,一个是 is
比较,前者是用来比较值是不是相等,后者是判断是不是属于同一个对象。其实,在 python 中,is 比较便是通过 id()
来实现的。当两个 Objec 拥有相同的 id 时,便会认为这是两个相同的对象。
因此,可以认为:object1 is object2
等价于 id(object1) == id(object2)
。
例外
今天在 v2ex 看到一个好玩的帖子(https://www.v2ex.com/t/336021 ),提到了 id([1]) == id([2])
会返回 True
。
而我跑了一组数据,结果也是很有意思:
>>> id([1])
4391579520
>>> id([2])
4391579520
>>> a = [1]
>>> b = [1]
>>> id([1])
4391757944
>>> id([2])
4391757944
>>> id(a)
4391579520
>>> id(b)
4391641672
>>> id([1])
4391787072
>>> id([2])
4391787072
因为在文档中已经提到了,两个不同生命域的对象可能会有相同的 id,因此出现这种情况也不例外,毕竟 [1]
,[2]
,现在的确是两个不同的生命域的常量,因为这两个常量没有被任何变量引用,当使用结束之后,便会被回收掉,因此会出现两个不同的常量出现相同 id 的情况。
当给他们添加引用,会发现这个 id 就被确定到这个一个 [1]
常量上了,这是因为 这个 [1]
的生命域并没有结束(还被引用不能被回收),因此,新的 list object 不会再使用这个 id 而是换了新的 id。
2018.11.16 更新
今天又看到一种新的验证方式,定义如下类:
class WTF(object):
def __init__(self): print("I")
def __del__(self): print("D")
is 比较时,两个对象先创建再比较:
In [2]: WTF() is WTF()
I
I
D
D
Out[2]: False
id 比较时,当对象的 id 被获得之后,对象就会被注销,新对象恰好会分配在原内存空间,因此得到 True。
In [3]: id(WTF()) == id(WTF())
I
D
I
D
Out[3]: True