def zhuangshi(cls):
def inner():
pass
return inner
class A:
pass
print(zhuangshi(A) is zhuangshi(A))
print(id(zhuangshi(A)) == id(zhuangshi(A)))
print(id(zhuangshi(A)))
print(id(zhuangshi(A)))
控制台输出结果如下:
False
True
31665416
31665416
惊呆! 为什么两个对象的内存地址都一样,为何 is 运行结果是false?
楼上都没答到点子上,这个现象与 gc 有关,属于未定义行为。
事情是这样的:
执行
zhuangshi(A) is zhuangshi(A)
时,表达式从左到右求值,先运算第一个zhuangshi(A)
,并将返回值存在一个临时变量,假设为tmp1
;再运算第二个,返回值存在tmp2
。此时内存中实际上有两个inner
的副本,各被一个引用tmp1
tmp2
指向,它们地址当然是不同的,因此is
的结果为False
。再看第二个例子:
执行
id(zhuangshi(A)) == id(zhuangshi(A))
时,表达式从左到右、从内向外求值。先运算zhuangshi(A)
,再将返回值传给id
,最后我们得到一个整数。注意此处与上一个例子不同,此时已经没有任何指向 inner 的引用,因此垃圾回收器可以将其回收。待对第二个表达式求值时,有一定的概率 Python 会在先前的 inner 对象的地址上创建新的 inner 对象,从而导致两个地址相同。总而言之,看上去它们是同一个对象,实际上它们是先后被创建在同一个地址上的两个不同对象,因此有相同的 id。