Python __getattribute__ vs __getattr__ 淺談

相信大家看到這個標(biāo)題的時候也會立馬在腦海里面過一遍干毅,覺得大多數(shù)時候我們并不太需要關(guān)注getattributegetattr的一些細(xì)節(jié)(至少我自己吧:)),
一般情況下消費(fèi)我們自定義的類的時候陷猫,我們對類的結(jié)構(gòu)都了解,不會刻意偏離只厘,造成一些屬性訪問的錯誤烙丛。

不過作為一個有好奇心有追求有氣質(zhì)的python寶寶舅巷,怎么可能不稍稍研究一下呢羔味。好吧,其實是在github上讀到一個開源項目sinaweibopy的源碼才看的钠右,代碼挺有意思赋元,正好當(dāng)作一個實用的例子,來看看如何自定義實現(xiàn)gettattr讓代碼更加的動態(tài)優(yōu)雅:

# 例子在原來的基礎(chǔ)上簡化了一下飒房,排除依賴和干擾搁凸,詳細(xì)參見原項目
class UrlGenerator(object):
    def __init__(self, root_url):
        self.url = root_url

    def __getattr__(self, item):
        if item == 'get' or item == 'post':
            print self.url
        return UrlGenerator('{}/{}'.format(self.url, item))


url_gen = UrlGenerator('http://xxxx')
url_gen.users.show.get

>>> http://xxxx/users/show

充分利用getattr會在沒有查找到相應(yīng)實例屬性時被調(diào)用的特點(diǎn),方便的通過鏈?zhǔn)秸{(diào)用生成對應(yīng)的url狠毯,源代碼中在碰到http method的時候返回一個
可調(diào)用的對象更加的優(yōu)雅护糖,鏈?zhǔn)降牟僮鞑粌H優(yōu)雅而且還能很好的說明調(diào)用的接口的意義(restful的接口啦)。

既然能通過定制類的getattr自定義方法來實現(xiàn)一些優(yōu)雅的功能嚼松,自然我們也要對它有一些了解嫡良,包括和它相似的自定義方法getattribute

1. 用作實例屬性的獲取和攔截

當(dāng)訪問某個實例屬性時锰扶, getattribute會被無條件調(diào)用,如未實現(xiàn)自己的getattr方法寝受,會拋出AttributeError提示找不到這個屬性坷牛,如果自定義了自己getattr方法的話,方法會在這種找不到屬性的情況下被調(diào)用很澄,比如上面的例子中的情況京闰。所以在找不到屬性的情況下通過實現(xiàn)自定義的getattr方法來實現(xiàn)一些功能是一個不錯的方式,因為它不會像getattribute方法每次都會調(diào)用可能會影響一些正常情況下的屬性訪問:

class Test(object):
    def __init__(self, p):
        self.p = p

    def __getattr__(self, item):
        return 'default'

t = Test('p1')
print t.p
print t.p2

>>> p1
>>> default

2. 自定義getattribute的時候防止無限遞歸

因為getattribute在訪問屬性的時候一直會被調(diào)用甩苛,自定義的getattribute方法里面同時需要返回相應(yīng)的屬性蹂楣,通過self.__dict__取值會繼續(xù)向下調(diào)用getattribute,造成循環(huán)調(diào)用:

class AboutAttr(object):
    def __init__(self, name):
        self.name = name

    def __getattribute__(self, item):
        try:
            return super(AboutAttr, self).__getattribute__(item)
        except KeyError:
            return 'default'

這里通過調(diào)用綁定的super對象來獲取隊形的屬性讯蒲,對新式類來說其實和object.__getattribute__(self, item)一樣的道理:

  • 默認(rèn)情況下自定義的類會從object繼承getattribute方法捐迫,對于屬性的查找是完全能用的
  • getattribute的實現(xiàn)感覺還是挺抽象化的,只需要綁定相應(yīng)的實例對象和要查找的屬性名稱就行

3.同時覆蓋掉getattribute和getattr的時候爱葵,在getattribute中需要模仿原本的行為拋出AttributeError或者手動調(diào)用getattr

class AboutAttr(object):
    def __init__(self, name):
        self.name = name

    def __getattribute__(self, item):
        try:
            return super(AboutAttr, self).__getattribute__(item)
        except KeyError:
            return 'default'
        except AttributeError as ex:
            print ex

    def __getattr__(self, item):
        return 'default'

at = AboutAttr('test')
print at.name
print at.not_exised

>>>test
>>>'AboutAttr' object has no attribute 'not_exised'
>>>None

上面例子里面的getattr方法根本不會被調(diào)用施戴,因為原本的AttributeError被我們自行處理并未拋出,也沒有手動調(diào)用getattr萌丈,所以訪問not_existed的結(jié)果是None而不是default.

關(guān)于getattribute和getattr的特性與區(qū)別就扯到這赞哗,要更深入的了解可以自行g(shù)oogle,編寫高質(zhì)量代碼:改善Python程序的91個建議這本書里面也有一些詳細(xì)的介紹辆雾。

參考資料:

python doc about getattr & getattribute

編寫高質(zhì)量代碼:改善Python程序的91個建議

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肪笋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子度迂,更是在濱河造成了極大的恐慌藤乙,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惭墓,死亡現(xiàn)場離奇詭異坛梁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)腊凶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門划咐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人钧萍,你說我怎么就攤上這事褐缠。” “怎么了风瘦?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵队魏,是天一觀的道長。 經(jīng)常有香客問我万搔,道長胡桨,這世上最難降的妖魔是什么俐载? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮登失,結(jié)果婚禮上遏佣,老公的妹妹穿的比我還像新娘。我一直安慰自己揽浙,他們只是感情好状婶,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著馅巷,像睡著了一般膛虫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钓猬,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天稍刀,我揣著相機(jī)與錄音,去河邊找鬼敞曹。 笑死账月,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澳迫。 我是一名探鬼主播局齿,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼橄登!你這毒婦竟也來了抓歼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤拢锹,失蹤者是張志新(化名)和其女友劉穎谣妻,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卒稳,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹋半,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了展哭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湃窍。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡闻蛀,死狀恐怖匪傍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情觉痛,我是刑警寧澤役衡,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站薪棒,受9級特大地震影響手蝎,放射性物質(zhì)發(fā)生泄漏榕莺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一棵介、第九天 我趴在偏房一處隱蔽的房頂上張望钉鸯。 院中可真熱鬧,春花似錦邮辽、人聲如沸唠雕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岩睁。三九已至,卻和暖如春揣云,著一層夾襖步出監(jiān)牢的瞬間捕儒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工邓夕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刘莹,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓焚刚,卻偏偏與公主長得像栋猖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子汪榔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 定義類并創(chuàng)建實例 在Python中蒲拉,類通過 class 關(guān)鍵字定義。以 Person 為例痴腌,定義一個Person類...
    績重KF閱讀 3,924評論 0 13
  • 1.1. 摘要 定義描述器, 總結(jié)描述器協(xié)議雌团,并展示描述器是怎么被調(diào)用的。展示一個自定義的描述器和包括函數(shù)士聪,屬性(...
    mutex73閱讀 442評論 0 2
  • 曾已何時锦援,人們從悲秋的情懷中走了出來,開始喜歡上樹葉從枝頭落地剥悟,都舍不得將它掃去灵寺,于是初冬變得格外美麗。 船來只往...
    東觀閱讀 463評論 0 3
  • 不是什么溫柔的人 但是還是會不斷忍我的臭脾氣 不會甜到齁 更多反而是損 嘴欠的要命 孩子氣(? ̄?^ ̄??) 所以...
    超愛豬豬橋閱讀 159評論 0 0