成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

關(guān)于Python類屬性與實(shí)例屬性的討論

neroneroffy / 2447人閱讀

摘要:之所以想寫這個(gè)文章是因?yàn)榕銮煽吹骄W(wǎng)上一篇關(guān)于中類屬性及實(shí)例屬性區(qū)別的帖子。中屬性的獲取對于屬性,我們通常采用類屬性或?qū)嵗龑傩缘男问秸{(diào)用。最關(guān)鍵的地方在于兩點(diǎn)理解是如何利用查找樹的機(jī)制來模仿類及實(shí)例之間的關(guān)系理解動(dòng)態(tài)語言是可以動(dòng)態(tài)設(shè)置屬性的


標(biāo)題名字有點(diǎn)長。
之所以想寫這個(gè)文章是因?yàn)榕銮煽吹骄W(wǎng)上一篇關(guān)于Pyhon中類屬性及實(shí)例屬性區(qū)別的帖子。因?yàn)槲抑耙脖贿@個(gè)問題困擾過,今天碰巧看到了這篇帖子,發(fā)現(xiàn)帖子的作者只是描述了現(xiàn)象,然后對原因的解釋比較含糊,并沒有從根本上解釋這個(gè)問題,所以才想寫一下我對這個(gè)問題的想法。


性子急的可以直接跳到最后看總結(jié)。
原帖子地址

問題描述

為了方便對比,我還是使用原帖子的例子:

class AAA():  
    aaa = 10  

# 情形1   
obj1 = AAA()  
obj2 = AAA()   
print obj1.aaa, obj2.aaa, AAA.aaa   

# 情形2  
obj1.aaa += 2  
print obj1.aaa, obj2.aaa, AAA.aaa   

# 情形3  
AAA.aaa += 3  
print obj1.aaa, obj2.aaa, AAA.aaa  

情形1的結(jié)果是:10 10 10;
情形2的結(jié)果是:12 10 10;
情形3的結(jié)果是:12 13 13;

首先為什么會有這個(gè)問題呢?
因?yàn)?b>aaa屬性被稱為類屬性,既然是類屬性,那么根據(jù)從C++/Java這種靜態(tài)語言使用的經(jīng)驗(yàn)來判斷,類屬性應(yīng)該是為其實(shí)例所共享的。很自然的,既然是共享關(guān)系,那么從類的層次改變aaa的值,自然其實(shí)例的aaa的值也要跟著變化了。
可是情形3的情況卻說明,上面的說法是錯(cuò)的。
錯(cuò)哪里呢?
要從Python的類屬性講起

Python中類屬性的含義

Python屬于動(dòng)態(tài)強(qiáng)類型的語言,在很多地方和靜態(tài)語言不同,因此,不能把靜態(tài)語言的規(guī)則套到動(dòng)態(tài)語言上來。其中,類屬性就是一個(gè)很好的例子。
Python中屬性的獲取
對于屬性,我們通常采用類.屬性實(shí)例.屬性的形式調(diào)用。
例如上例中的AAA.aaa屬于類.屬性形式,obj1.aaa屬于實(shí)例.屬性的形式
Python中屬性的設(shè)置
對于屬性的設(shè)置我們通常采用類.屬性 = 值實(shí)例.屬性 = 值的形式
例如obj1.aaa = 3

上例中obj1.aaa += 2等價(jià)于obj1.aaa = obj1.aaa + 2,這句話包含了屬性獲取屬性設(shè)置兩個(gè)操作

OK,重點(diǎn)來了,Python中屬性的獲取和設(shè)置的機(jī)制與靜態(tài)語言是不同的,正是背后機(jī)制的不同,導(dǎo)致了Python中類屬性不一定是為其實(shí)例所共享的

Python中屬性查找機(jī)制

Python中屬性的獲取存在一個(gè)向上查找機(jī)制,還是拿上面的例子做說明:
Python中一切皆對象,AAA屬于類對象,obj1屬于實(shí)例對象,從對象的角度來看,AAAobj1是兩個(gè)無關(guān)的對象,但是,Python通過下面的查找樹建立了類對象AAA與實(shí)例對象obj1obj2之間的關(guān)系。
如圖所示

        AAA
         |
       -----
      |     |  
    obj1   obj2

(圖畫的不好,見諒 -.-!!!)
當(dāng)調(diào)用AAA.aaa時(shí),直接從AAA獲取其屬性aaa。
但是情形1中調(diào)用obj1.aaa時(shí),Python按照從obj1AAA的順序由下到上查找屬性aaa
值得注意的這時(shí)候obj1是沒有屬性aaa,于是,Python到類AAA中去查找,成功找到,并顯示出來。所以,從現(xiàn)象上來看,AAA的屬性aaa確實(shí)是共享給其所有實(shí)例的,雖然這里只是從查找樹的形式模擬了其關(guān)系。

Python中的屬性設(shè)置

原帖子的作者也指出問題的關(guān)鍵在于情形2中obj1.aaa += 2。
為什么呢?
上面我們指出obj.aaa += 2包含了屬性獲取屬性設(shè)置兩個(gè)操作。即obj1.aaa += 2等價(jià)于obj1.aaa = obj1.aaa + 2
其中等式右側(cè)的obj.aaa屬于屬性獲取,其規(guī)則是按照上面提到的查找規(guī)則進(jìn)行,即,這時(shí)候,獲取到的是AAA的屬性aaa,所以等式左側(cè)的值為12。
第二個(gè)操作是屬性設(shè)置,即obj.aaa = 12。當(dāng)發(fā)生屬性設(shè)置的時(shí)候,obj1這個(gè)實(shí)例對象沒有屬性aaa,因此會為自身動(dòng)態(tài)添加一個(gè)屬性aaa。
由于從對象的角度,類對象和實(shí)例對象屬于兩個(gè)獨(dú)立的對象,所以,這個(gè)aaa屬性只屬于obj1,也就是說,這時(shí)候類對象AAA和實(shí)例對象aaa各自有一個(gè)屬性aaa。
那么,在情形3中,再次調(diào)用obj1.aaa時(shí),按照屬性調(diào)用查找規(guī)則,這個(gè)時(shí)候獲取到的是實(shí)例對象obj1的屬性aaa,而不是類對象AAA的屬性aaa

對問題探討的總結(jié)

到這里就可以完滿解釋上面的問題:
1. Python中屬性的獲取是按照從下到上的順序來查找屬性;
2. Python中的類和實(shí)例是兩個(gè)完全獨(dú)立的對象;
3. Python中的屬性設(shè)置是針對對象本身進(jìn)行的;

對情形1的解釋

因?yàn)?strong>Python中的屬性獲取是按照從下到上的順序來查找的,所以在情形1:

obj1 = AAA()  
obj2 = AAA()

實(shí)例對象obj1obj2不存在屬性aaa。
證明如下:

>>> obj1.__dict__
{}
>>> obj2.__dict__
{}

所以,此時(shí),obj1.aaa, obj2.aaa, AAA.aaa實(shí)質(zhì)上都是指AAA.aaa。因此,輸出同樣的結(jié)果。

對情形2的解釋

因?yàn)?strong>Python中的類和實(shí)例是兩個(gè)完全獨(dú)立的對象且Python中的屬性設(shè)置是針對對象本身進(jìn)行的,所以在情形2:

obj1.aaa += 2  

實(shí)質(zhì)上是對實(shí)例對象obj1設(shè)置了屬性aaa,并賦值為12。證明如下:

>>> obj1.aaa = 3
>>> obj1.__dict__
{"aaa": 3}
>>> obj2.__dict__
{}

因此,再次調(diào)用obj1.aaa時(shí),將獲取到的是實(shí)例對象obj1的屬性aaa,而不是類對象AAA的屬性aaa。而對于實(shí)例對象obj2,由于其并沒有屬性aaa,所以調(diào)用obj2.aaa時(shí),獲取到的是AAA的屬性aaa。

對情形3的解釋

順利理解了前兩個(gè)情形,那么第3個(gè)情形就很容易了,改變AAA的屬性aaa只能影響到類對象AAA和實(shí)例對象obj2,不能影響obj1,因?yàn)椋?b>obj1存在aaa,在獲取時(shí),不會獲取到AAA的屬性。

寫在最后的話

問題本身很簡單,但是通過對這個(gè)問題的探討,可以深入理解Python作為一個(gè)動(dòng)態(tài)語言,在OOP的機(jī)制上與靜態(tài)語言的差別。
最關(guān)鍵的地方在于兩點(diǎn):
1. 理解Python是如何利用查找樹的機(jī)制來模仿類及實(shí)例之間的關(guān)系;
2. 理解動(dòng)態(tài)語言是可以動(dòng)態(tài)設(shè)置屬性的

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/37519.html

相關(guān)文章

  • Python學(xué)習(xí)之路30-接口:從協(xié)議到抽象基

    摘要:本篇內(nèi)容將從鴨子類型的動(dòng)態(tài)協(xié)議,逐漸過渡到使接口更明確能驗(yàn)證實(shí)現(xiàn)是否符合規(guī)定的抽象基類。抽象基類介紹完動(dòng)態(tài)實(shí)現(xiàn)接口后,現(xiàn)在開始討論抽象基類,它屬于靜態(tài)顯示地實(shí)現(xiàn)接口。標(biāo)準(zhǔn)庫中的抽象基類從開始,標(biāo)準(zhǔn)庫提供了抽象基類。 《流暢的Python》筆記。本篇是面向?qū)ο髴T用方法的第四篇,主要討論接口。本篇內(nèi)容將從鴨子類型的動(dòng)態(tài)協(xié)議,逐漸過渡到使接口更明確、能驗(yàn)證實(shí)現(xiàn)是否符合規(guī)定的抽象基類(Abst...

    LucasTwilight 評論0 收藏0
  • Python new 方法和 init 實(shí)例方法以及單例模式簡單討論

    摘要:中的類都是單例模式一天,一同事問我這樣一個(gè)問題。與方法屬于新式類,即屬于類。方法在實(shí)例被創(chuàng)建之后被調(diào)用,該方法僅僅是對方法創(chuàng)建的實(shí)例進(jìn)行一些初始化操作。需要注意的是,在重寫方法與方法的參數(shù)應(yīng)該保持一致,否則會有發(fā)生。 Python 中的類都是單例模式? 一天,一同事問我這樣一個(gè)問題。這是一個(gè)奇怪的問題,可能你也這么認(rèn)為。這里先不做解釋,我們先來看看 __new__ 和 __init__...

    FingerLiu 評論0 收藏0
  • Python學(xué)習(xí)之路28-符合Python風(fēng)格對象

    摘要:本篇繼續(xù)學(xué)習(xí)之路,實(shí)現(xiàn)更多的特殊方法以讓自定義類的行為跟真正的對象一樣。之所以要讓向量不可變,是因?yàn)槲覀冊谟?jì)算向量的哈希值時(shí)需要用到和的哈希值,如果這兩個(gè)值可變,那向量的哈希值就能隨時(shí)變化,這將不是一個(gè)可散列的對象。 《流暢的Python》筆記。本篇是面向?qū)ο髴T用方法的第二篇。前一篇講的是內(nèi)置對象的結(jié)構(gòu)和行為,本篇?jiǎng)t是自定義對象。本篇繼續(xù)Python學(xué)習(xí)之路20,實(shí)現(xiàn)更多的特殊方法以讓...

    Eric 評論0 收藏0
  • python 和元(metaclass)理解和簡單運(yùn)用

    摘要:什么是元類剛才說了,元類就是創(chuàng)建類的類。類上面的屬性,相信愿意了解元類細(xì)節(jié)的盆友,都肯定見過這個(gè)東西,而且為之好奇。使用了這個(gè)魔法方法就意味著就會用指定的元類來創(chuàng)建類了。深刻理解中的元類 (一) python中的類 今天看到一篇好文,然后結(jié)合自己的情況總結(jié)一波。這里討論的python類,都基于python2.7x以及繼承于object的新式類進(jìn)行討論。 首先在python中,所有東西都...

    zhangqh 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<