一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - 舉例講解Python中is和id的用法

舉例講解Python中is和id的用法

2020-05-29 11:19acmerfight Python

這篇文章主要介紹了舉例講解Python中is和id的用法,是Python學(xué)習(xí)當(dāng)中的基礎(chǔ)知識(shí),作者舉例進(jìn)行了簡單說明,需要的朋友可以參考下

(ob1 is ob2) 等價(jià)于 (id(ob1) == id(ob2))

首先id函數(shù)可以獲得對(duì)象的內(nèi)存地址,如果兩個(gè)對(duì)象的內(nèi)存地址是一樣的,那么這兩個(gè)對(duì)象肯定是一個(gè)對(duì)象。和is是等價(jià)的。Python源代碼為證。
 

?
1
2
3
4
5
6
7
8
9
10
11
static PyObject *
 cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
 int res = 0;
 switch (op) {
 case PyCmp_IS:
 res = (v == w);
 break;
 case PyCmp_IS_NOT:
res = (v != w);
 break;

但是請(qǐng)看下邊代碼的這種情況怎么會(huì)出現(xiàn)呢?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
In [1]: def bar(self, x):
...:   return self.x + y
...:
 
In [2]: class Foo(object):
...:   x = 9
...:   def __init__(self ,x):
...:     self.x = x
...:   bar = bar
...: 
 
In [3]: foo = Foo(5)
 
In [4]: foo.bar is Foo.bar
Out[4]: False
 
In [5]: id(foo.bar) == id(Foo.bar)
Out[5]: True

兩個(gè)對(duì)象用is判斷是False,用id判斷卻是True,這與我們已知的事實(shí)不符啊,這種現(xiàn)象該如何解釋呢?遇到這種情況最好的解決方法就是調(diào)用dis模塊去看下兩個(gè)比較語句到底做了什么。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
In [7]: dis.dis("id(foo.bar) == id(Foo.bar)")
     0 BUILD_MAP    10340
     3 BUILD_TUPLE   28527
     6 <46>    
     7 DELETE_GLOBAL  29281 (29281)
     10 STORE_SLICE+1
     11 SLICE+2   
     12 DELETE_SUBSCR
     13 DELETE_SUBSCR
     14 SLICE+2   
     15 BUILD_MAP    10340
     18 PRINT_EXPR 
     19 JUMP_IF_FALSE_OR_POP 11887
     22 DELETE_GLOBAL  29281 (29281)
     25 STORE_SLICE+1
 
In [8]: dis.dis("foo.bar is Foo.bar")
     0 BUILD_TUPLE   28527
     3 <46>    
     4 DELETE_GLOBAL  29281 (29281)
     7 SLICE+2   
     8 BUILD_MAP    8307
     11 PRINT_EXPR 
     12 JUMP_IF_FALSE_OR_POP 11887
     15 DELETE_GLOBAL  29281 (29281)

真實(shí)情況是當(dāng)執(zhí)行.操作符的時(shí)候,實(shí)際是生成了一個(gè)proxy對(duì)象,foo.bar is Foo.bar的時(shí)候,兩個(gè)對(duì)象順序生成,放在棧里相比較,由于地址不同肯定是False,但是id(foo.bar) == id(Foo.bar)的時(shí)候就不同了,首先生成foo.bar,然后計(jì)算foo.bar的地址,計(jì)算完之后foo.bar的地址之后,就沒有任何對(duì)象指向foo.bar了,所以foo.bar對(duì)象就會(huì)被釋放。然后生成Foo.bar對(duì)象,由于foo.bar和Foo.bar所占用的內(nèi)存大小是一樣的,所以又恰好重用了原先foo.bar的內(nèi)存地址,所以id(foo.bar) == id(Foo.bar)的結(jié)果是True。

下面內(nèi)容由郵件Leo Jay大牛提供,他解釋的更加通透。

用id(expression a) == id(expression b)來判斷兩個(gè)表達(dá)式的結(jié)果是不是同一個(gè)對(duì)象的想法是有問題的。

foo.bar 這種形式叫 attribute reference [1],它是表達(dá)式的一種。foo是一個(gè)instance object,bar是一個(gè)方法,這個(gè)時(shí)候表達(dá)式foo.bar返回的結(jié)果叫method object [2]。根據(jù)文檔:

    When an instance attribute is referenced that isn't a data attribute,
    its class is searched. If the name denotes a valid class attribute
    that is a function object, a method object is created by packing
    (pointers to) the instance object and the function object just found
    together in an abstract object: this is the method object.

foo.bar本身并不是簡單的名字,而是表達(dá)式的計(jì)算結(jié)果,是一個(gè) method object,在id(foo.bar)這樣的表達(dá)式里,method object只是一個(gè)臨時(shí)的中間變量而已,對(duì)臨時(shí)的中間變量做id是沒有意義的。
一個(gè)更明顯的例子是,
 

?
1
print id(foo.bar) == id(foo.__init__)

輸出的結(jié)果也是True

看 id 的文檔[3]:

    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.
    CPython implementation detail: This is the address of the object in memory.

只有你能保證對(duì)象不會(huì)被銷毀的前提下,你才能用 id 來比較兩個(gè)對(duì)象。所以,如果你非要比的話,得這樣寫:
 

?
1
2
3
fb = foo.bar
Fb = Foo.bar
print id(fb) == id(Fb)

即把兩個(gè)表達(dá)式的結(jié)果綁定到名字上,再來比是不是同一個(gè)對(duì)象,你才能得到正確的結(jié)果。

is表達(dá)式 [4] 也是一樣的,你現(xiàn)在得到了正確的結(jié)果,完全是因?yàn)?CPython 現(xiàn)在的實(shí)現(xiàn)細(xì)節(jié)決定的。現(xiàn)在的is的實(shí)現(xiàn),是左右兩邊的對(duì)象都計(jì)算出來,然后再比較這兩個(gè)對(duì)象的地址是否一樣。萬一哪天改成了,先算左邊,保存地址,把左邊釋放掉,再算右邊,再比較的話,你的is的結(jié)果可能就錯(cuò)了。官方文檔里也提到了這個(gè)問題 [5]。我認(rèn)為正確的方法也是像id那樣,先把左右兩邊都計(jì)算下來,并顯式綁定到各自的名字上,然后再用is判斷。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 四虎影院在线免费播放 | 欧美成a人片免费看久久 | 91大神亚洲影视在线 | 无限观看社区在线视频 | 日日日操 | 天天综合色天天综合网 | 蜜桃麻豆 | 免费日批软件 | 久久久精品免费视频 | 色综合视频一区二区三区 | 亚洲 欧美 国产 综合 在线 | 日产乱码卡1卡2卡三免费 | 色综合久久天天综合 | 四虎影院在线免费观看 | 久久www免费人成高清 | 免费370理论片中文字幕 | 韩国伊人 | 99国产精品免费观看视频 | 日本中文字幕在线观看视频 | 国产三级精品三级男人的天堂 | 亚欧美综合| 国产麻豆精品免费视频 | 精品久久香蕉国产线看观看麻豆 | 国产亚洲精品第一综合linode | 国产123区在线视频观看 | 色爱导航| 国产极品麻豆91在线 | 美女被草出水 | 6080伦理久久精品亚洲 | 贵妇的私人性俱乐部 | 亚洲免费网站在线观看 | 97蝌蚪自拍自窝 | 2021国产精品视频 | 国产一区精品 | 色婷婷婷丁香亚洲综合不卡 | 天天综合网网欲色 | 99精品国产综合久久久久 | 色人阁导航 | 日本伊人久久 | 手机看片黄色 | 婷婷福利 |