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

資訊專欄INFORMATION COLUMN

Python中幾種屬性訪問的區(qū)別

zhouzhou / 473人閱讀

摘要:起步的提供一系列和屬性訪問有關(guān)的特殊方法。本文闡述它們的區(qū)別和用法。屬性的訪問機(jī)制一般情況下,屬性訪問的默認(rèn)行為是從對象的字典中獲取,并當(dāng)獲取不到時(shí)會沿著一定的查找鏈進(jìn)行查找。則這個(gè)類的對象稱為描述符。

起步

python的提供一系列和屬性訪問有關(guān)的特殊方法:__get__, __getattr__, __getattribute__, __getitem__ 。本文闡述它們的區(qū)別和用法。

屬性的訪問機(jī)制

一般情況下,屬性訪問的默認(rèn)行為是從對象的字典中獲取,并當(dāng)獲取不到時(shí)會沿著一定的查找鏈進(jìn)行查找。例如 a.x 的查找鏈就是,從 a.__dict__["x"] ,然后是 type(a).__dict__["x"] ,再通過 type(a) 的基類開始查找。

若查找鏈都獲取不到屬性,則拋出 AttributeError 異常。

__getattr__ 方法

這個(gè)方法是當(dāng)對象的屬性不存在是調(diào)用。如果通過正常的機(jī)制能找到對象屬性的話,不會調(diào)用 __getattr__ 方法。

class A:
    a = 1
    def __getattr__(self, item):
        print("__getattr__ call")
        return item

t = A()
print(t.a)
print(t.b)
# output
1
__getattr__ call
b
__getattribute__ 方法

這個(gè)方法會被無條件調(diào)用。不管屬性存不存在。如果類中還定義了 __getattr__ ,則不會調(diào)用 __getattr__() 方法,除非在 __getattribute__ 方法中顯示調(diào)用__getattr__() 或者拋出了 AttributeError 。

class A:
    a = 1
    def __getattribute__(self, item):
        print("__getattribute__ call")
        raise AttributeError

    def __getattr__(self, item):
        print("__getattr__ call")
        return item

t = A()
print(t.a)
print(t.b)

所以一般情況下,為了保留 __getattr__ 的作用,__getattribute__() 方法中一般返回父類的同名方法:

def __getattribute__(self, item):
    return object.__getattribute__(self, item)

使用基類的方法來獲取屬性能避免在方法中出現(xiàn)無限遞歸的情況。

__get__ 方法

這個(gè)方法比較簡單說明,它與前面的關(guān)系不大。

如果一個(gè)類中定義了 __get__(), __set__()__delete__() 中的任何方法。則這個(gè)類的對象稱為描述符。

class Descri(object):
    def __get__(self, obj, type=None):
        print("call get")

    def __set__(self, obj, value):
        print("call set")


class A(object):
    x = Descri()

a = A()
a.__dict__["x"] = 1  # 不會調(diào)用 __get__
a.x                  # 調(diào)用 __get__

如果查找的屬性是在描述符對象中,則這個(gè)描述符會覆蓋上文說的屬性訪問機(jī)制,體現(xiàn)在查找鏈的不同,而這個(gè)行文也會因?yàn)檎{(diào)用的不同而稍有不一樣:

如果調(diào)用是對象實(shí)例(題目中的調(diào)用方式),a.x 則轉(zhuǎn)換為調(diào)用: 。type(a).__dict__["x"].__get__(a, type(a))

如果調(diào)用的是類屬性, A.x 則轉(zhuǎn)換為:A.__dict__["x"].__get__(None, A)

其他情況見文末參考資料的文檔

__getitem__ 方法

這個(gè)調(diào)用也屬于無條件調(diào)用,這點(diǎn)與 __getattribute__ 一致。區(qū)別在于 __getitem__ 讓類實(shí)例允許 [] 運(yùn)算,可以這樣理解:

__getattribute__ 適用于所有 . 運(yùn)算符;

__getitem__ 適用于所有 [] 運(yùn)算符。

class A(object):
    a = 1

    def __getitem__(self, item):
        print("__getitem__ call")
        return item

t = A()
print(t["a"])
print(t["b"])

如果僅僅想要對象能夠通過 [] 獲取對象屬性可以簡單的:

def __getitem(self, item):
    return object.__getattribute__(self, item)
總結(jié)

當(dāng)這幾個(gè)方法同時(shí)出現(xiàn)可能就會擾亂你了。我在網(wǎng)上看到一份示例還不錯(cuò),稍微改了下:

class C(object):
    a = "abc"

    def __getattribute__(self, *args, **kwargs):
        print("__getattribute__() is called")
        return object.__getattribute__(self, *args, **kwargs)

    #        return "haha"
    def __getattr__(self, name):
        print("__getattr__() is called ")
        return name + " from getattr"

    def __get__(self, instance, owner):
        print("__get__() is called", instance, owner)
        return self

    def __getitem__(self, item):
        print("__getitem__ call")
        return object.__getattribute__(self, item)

    def foo(self, x):
        print(x)


class C2(object):
    d = C()


if __name__ == "__main__":
    c = C()
    c2 = C2()
    print(c.a)
    print(c.zzzzzzzz)
    c2.d
    print(c2.d.a)
    print(c["a"])

可以結(jié)合輸出慢慢理解,這里還沒涉及繼承關(guān)系呢??傊?,每個(gè)以 __ get 為前綴的方法都是獲取對象內(nèi)部數(shù)據(jù)的鉤子,名稱不一樣,用途也存在較大的差異,只有在實(shí)踐中理解它們,才能真正掌握它們的用法。

參考

https://docs.python.org/3/ref...

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

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

相關(guān)文章

  • JS幾種包含for遍歷方式

    摘要:區(qū)別遍歷數(shù)組常用調(diào)用數(shù)組的每個(gè)元素,并將元素傳遞給回調(diào)函數(shù)這種循環(huán)的問題在于無法中途跳出循環(huán),和命令不能奏效和都返回?cái)?shù)組,返回的與原數(shù)組長度相同只返回符合條件的結(jié)果一個(gè)值和返回布爾值遍歷對象所有的可枚舉屬性主要是為了遍歷對象而設(shè)計(jì)的,不適 forEach,map,filter區(qū)別 forEach 遍歷數(shù)組常用(調(diào)用數(shù)組的每個(gè)元素,并將元素傳遞給回調(diào)函數(shù)) let arr = [1,2...

    jcc 評論0 收藏0
  • js幾種跨域方法

    摘要:四通過跨域一個(gè)頁面嵌入一個(gè)外域的頁面雖然兩個(gè)窗體之前能獲取彼此的對象,但是卻拿不到上的屬性和方法,例如一個(gè)頁面嵌入一個(gè)的我是父窗體的方法嵌入的窗體跟的域名不同,很明顯是跨域的,雖然能獲取到對象,但是拿不到頁面的任何方法和屬性。 js跨域是指通過js在不同域之間進(jìn)行相互通信或者數(shù)據(jù)傳輸,只要協(xié)議,域名,端口號其中有一個(gè)不同,就是跨域。下面總結(jié)一下我了解到的常用的跨域方法。 一:通過jso...

    XboxYan 評論0 收藏0
  • CSS幾種常用選擇器

    摘要:類和的背景顏色都為白色大于號指子代元素子代選擇器類下的類元素的背景顏色為白色空格指后代元素后代選擇器類下的所有類元素的背景顏色為白色與子代選擇器不同,后代選擇器可以包含下的所有元素,包括子孫加號指相鄰元素相鄰選擇器緊接在類下的類元素的 類a和b的背景顏色都為白色 大于號‘ > ’指子代元素(子代選擇器) .a>.b{ background-color:#fff; } 類a下的類...

    趙連江 評論0 收藏0
  • 通過面試題,讓我們來了解Collection

    摘要:說一說迭代器通過集合對象獲取其對應(yīng)的對象判斷是否存在下一個(gè)元素取出該元素并將迭代器對象指向下一個(gè)元素取出元素的方式迭代器。對于使用容器者而言,具體的實(shí)現(xiàn)不重要,只要通過容器獲取到該實(shí)現(xiàn)的迭代器的對象即可,也就是方法。 前言 歡迎關(guān)注微信公眾號:Coder編程獲取最新原創(chuàng)技術(shù)文章和相關(guān)免費(fèi)學(xué)習(xí)資料,隨時(shí)隨地學(xué)習(xí)技術(shù)知識!** 本章主要介紹Collection集合相關(guān)知識,結(jié)合面試中會提到...

    HelKyle 評論0 收藏0
  • 手撕面試官系列(五):Tomcat+Mysql+設(shè)計(jì)模式面試專題

    摘要:面試題答案領(lǐng)取方式見主頁的缺省端口是多少,怎么修改有哪幾種運(yùn)行模式優(yōu)化有幾種部署方式容器是如何創(chuàng)建類實(shí)例用到了什么原理如何優(yōu)化內(nèi)存怎樣調(diào)優(yōu)垃圾回收怎樣策略調(diào)優(yōu)怎樣共享處理怎樣添加遠(yuǎn)程監(jiān)控專業(yè)點(diǎn)的分析工具有哪些關(guān)于的數(shù)目怎樣監(jiān)視的內(nèi)存使用情況 TomcatshowImg(https://segmentfault.com/img/remote/1460000019788819);(面試題+...

    GraphQuery 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<