在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Java  Python/ python 中is 相當(dāng)于比較兩個對象的id,這個怎么解釋

python 中is 相當(dāng)于比較兩個對象的id,這個怎么解釋

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)))

控制臺輸出結(jié)果如下:
False
True
31665416
31665416
驚呆! 為什么兩個對象的內(nèi)存地址都一樣,為何 is 運行結(jié)果是false?

回答
編輯回答
硬扛

== 是比較兩個對象的值是否相等。
is 除了比較對象的值是否相等,還涉及到比較兩個對象的內(nèi)存地址是否相等。

>>> type(zhuangshi(A))
<class 'function'>
>>> zhuangshi(A)
<function zhuangshi.<locals>.inner at 0x7f7823a98b70> # 注意查看最后的內(nèi)存地址
>>> zhuangshi(A)
<function zhuangshi.<locals>.inner at 0x7f78208ac7b8> # 注意查看最后的內(nèi)存地址
>>> c, d = A, A
>>> type(c)
<class 'type'>
>>> type(d)
<class 'type'>
>>> c
<class '__main__.A'>
>>> d
<class '__main__.A'>
>>>
>>> c is d
True
>>>

綜上比較,分明是 zhuangshi 這個類定義的是 返回一個 inner 對象,每次調(diào)用都會執(zhí)行一次 inner 函數(shù),所以調(diào)用的內(nèi)存地址是不一樣的。

2017年10月18日 10:59
編輯回答
萌面人

樓上都沒答到點子上,這個現(xiàn)象與 gc 有關(guān),屬于未定義行為。

事情是這樣的:

執(zhí)行 zhuangshi(A) is zhuangshi(A) 時,表達式從左到右求值,先運算第一個 zhuangshi(A),并將返回值存在一個臨時變量,假設(shè)為 tmp1;再運算第二個,返回值存在 tmp2。此時內(nèi)存中實際上有兩個 inner 的副本,各被一個引用 tmp1 tmp2 指向,它們地址當(dāng)然是不同的,因此 is 的結(jié)果為 False。

再看第二個例子:

執(zhí)行 id(zhuangshi(A)) == id(zhuangshi(A)) 時,表達式從左到右、從內(nèi)向外求值。先運算 zhuangshi(A),再將返回值傳給 id,最后我們得到一個整數(shù)。注意此處與上一個例子不同,此時已經(jīng)沒有任何指向 inner 的引用,因此垃圾回收器可以將其回收。待對第二個表達式求值時,有一定的概率 Python 會在先前的 inner 對象的地址上創(chuàng)建新的 inner 對象,從而導(dǎo)致兩個地址相同。

總而言之,看上去它們是同一個對象,實際上它們是先后被創(chuàng)建在同一個地址上的兩個不同對象,因此有相同的 id。

2017年3月6日 08:29
編輯回答
青瓷
print(zhuangshi(A) is zhuangshi(A))等價于
a, b = zhuangshi(A), zhuangshi(A)
print(a is b)  #False
print(id(a) == id(b)) #False

print(id(zhuangshi(A)) == id(zhuangshi(A)))等價于
a, b = id(zhuangshi(A)), id(zhuangshi(A))
print(a == b)    #True 兩次id相同所以true
2017年11月27日 06:07