id()返回对象的唯一身份标识,在CPython中即是对象在内存中的地址,具有非重叠生命周期的两个对象可能有相同的id。
is判断两个对象是不是同一个对象,逻辑是判断同一时刻这两个对象的id是否相同。
代码版本:3.6.3;文档版本:3.6.6
id()本来没啥写的,我一直的理解就是返回对象在内存中的地址。
直到有一次:
class A:
def aa(self):
pass
class B:
def ba(self):
pass
def bb(self):
pass
@classmethod
def bc(cls):
pass
@staticmethod
def bd():
pass
def __init__(self):
pass
a = A()
b = B()
print(id(a.aa))
print(id(b.ba))
print(id(b.bb))
print(id(b.bc))
print(id(b.__init__))
print(id(b.bd))
print(id(b.__hash__))
# 结果:
# 2933781120456
# 2933781120456
# 2933781120456
# 2933781120456
# 2933781120456
# 2933804461728
# 2933804434768
什么?同一个类或不同类之间的实例方法、类方法、重写父类方法的id竟然都一样??这怎么可能,明明是不同的对象啊,怎么会id相同呢?
看官方文档怎么说:
id
(object)Return the “identity” of an object. This is an 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.CPython implementation detail: This is the address of the object in memory.
噢?具有不重叠生命周期的两个对象可能具有相同的id!
噢?id()原来返回的是对象的身份标识!在CPython中id(o)才是对象在内存中的地址!好吧id()是什么是理解了,那上面的例子为什么id一样呢?方法的生命周期不重叠?还用了同一块内存?
那也就是说,程序运行起来后,有这么一个固定的内存,当我调用实例的什么方法,它就指向什么方法,不论是哪个实例的哪个方法。用谁就指向谁,用完就拜拜。
这样的话上面的例子是明白了,可又想到,is不就是判断id吗?那id相同is岂不就返回True了?这不可能吧
class B:
def ba(self):
pass
def bb(self):
pass
b = B()
print(b.ba is b.bb) # False
print(id(b.ba) == id(b.bb)) # True
还好是false,可id明明一样啊,难道is还判断的两个对象的生命周期吗?
嗯?既然用完才拜拜,如果我站着茅坑不用,会怎么样?
class A:
def aa(self):
pass
class B:
def ba(self):
pass
def bb(self):
pass
@classmethod
def bc(cls):
pass
a = A()
b = B()
print(id(b.ba) == id(b.bb) == id(b.bc) == id(a.aa))
print(id(a.aa))
ba = b.ba # 把b.ba赋值给一个变量保存,相当于添加了一个引用,那就不算用完
print(id(ba))
print(id(b.bb))
print(id(a.aa))
# 结果:
# True
# 1746998085064
# 1746998085064
# 1746998086664
# 1746998086664
看,之前的内存还在用着,或者说引用还存在,于是就又新找了一个内存来干这个活。
那这样也能解释is返回false了,is判断时应该是把两个对象都接收,然后再判断id。两个对象都接收存起来就保证了两个进行is比较的对象必须在同一时刻都存在,即生命周期有重叠部分,就保证了必须是同一个对象id才会相同,is判断就不会失误了。
关于id()和is的关系文档也有描述
Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The ‘
is
’ operator compares the identity of two objects; theid()
function returns an integer representing its identity.