1. 程式人生 > >python中的內建屬性之__getatrribute__

python中的內建屬性之__getatrribute__

python中有很多內建屬性常見的有:

__init__	__str__		__new__		__del__		__repr__	__getatrribute__等等

這次來說一下__getatrribute__屬性攔截器

> 先來一段程式碼:
在這裡插入圖片描述

> 執行結果:
在這裡插入圖片描述

分析:

19行的程式碼正常輸出了屬性subject2的值'屬性攔截器不執行正常返回'
但是18行的程式碼卻沒有輸出屬性subject1的值

這是為什麼呢?原因就是我們在第7行定義了內建屬性__getatrribute__屬性攔截器。

什麼是屬性攔截器?
和它的名字一樣只要一個類中有這個__getatrribute__,那麼在訪問這個類中的屬性**(有或者沒有!)

**時都會觸發它的執行,之後再根據__getatrribute__設定的方式獲得屬性內容。Python中只要定義了繼承object的類,就預設存在屬性攔截器,只不過是攔截後沒有進行任何操作,而是直接返回。所以我們可以自己改寫__getattribute__方法來實現相關功能,比如檢視許可權、列印log日誌等。

比如這裡我就設定了if語句如果訪問的屬性名字是subject2就是正常返回return object.__getattribute__(self,item)屬性subject2的值不做任何修改或者新增或者其他操作。

如果訪問subject1屬性的值,在這我讓他輸出屬性攔截器執行並返回無許可權訪問subject1

**

然後引用別人部落格的一個經常會犯的錯誤(當然我也錯過):

https://blog.csdn.net/yitiaodashu/article/details/78974596

**

class Tree(object):
    def __init__(self,name):
        self.name = name
        self.cate = "plant"
    def __getattribute__(self,item):
        if item.endswith("e"):
            return item.__getattribute__(self,item)
        else:
            return self.call_wind
    def call_wind(self):
        return "樹大招風"
aa = Tree("大樹")
print(aa.name)#因為name是以e結尾,所以返回的還是name,所以打印出"大樹"
aa.wind()#這個程式碼中因為wind不是以e結尾,所以返回self.call_wind的結果,列印的是"樹大招風"

上面的解釋正確嗎?
先說結果,關於print(aa.name)的解釋是正確的,但關於print(aa.wind)的解釋不對,為什麼呢?我們來分析一下,執行aa.wind時,先呼叫__getattribute__方法,
【這邊有的人又會有一個疑問我明明呼叫的是一個方法啊()又不是屬性為啥也會觸發屬性攔截器呢?我當初也是有疑惑的。這裡解釋一下,類中的方法,比如這裡aa.wind()其實際是由屬性wind指向這個函式的地址然後返回,之後加上()才呼叫這個函式的,所以實際上還是訪問一個屬性。其實所有函式都是由函式名+()組成的,函式名指向這個函式在記憶體中的位置然後加上執行符號()就可以呼叫找個函數了】經過判斷後,它返回的是self.call_wind(),即self.call_wind的執行結果,但當去呼叫aa這個物件的call_wind屬性時,前提是又要去呼叫__getattribute__方法,反反覆覆,沒完沒了,形成了遞迴呼叫且沒有退出機制,最終程式就掛了!所以這裡千萬不要在屬性攔截器中return 一個 self.屬性名而是 return object.__getattribute__(self,item)

在這裡插入圖片描述