1. 程式人生 > >通過描述符自定制@property的功能

通過描述符自定制@property的功能

由於 裝飾 int 結果 使用 屬性字典 room turn 初始

# 通過描述符自定制@property的功能

# 原始通過@property實現的功能:將類中定義的函數屬性,通過裝飾器@property將其封閉成數據屬性

class Room:
    def __init__(self, name, width, length):
        self.name = name
        self.width = width
        self.length = length

    @property
    def area(self):
        return self.width * self.length


r1 
= Room(廚房, 10, 4) print(r1.area) # 通過描述符與裝飾器自定制@property的功能 class Lazyproperty: # 定義描述符的類 def __init__(self, func): # 初始化時接收傳入的方法進行保存 self.func = func def __get__(self, instance, owner): if instance is None: # 解決直接用類調用屬性時傳不了實例而報錯的問題 return self res
= self.func(instance) setattr(instance, self.func.__name__, res) # 將res放入實例的字典中,如果下次再調用,根據優先級實例屬性高於非數據描述符,實例的屬性字典中有就直接從實例的屬性字典中找了 return res # 返回實例對象調用父類方法的結果,instance代表實例 class Room2: def __init__(self, name, width, length): self.name = name self.width = width self.length
= length @Lazyproperty # area=Lazyproperty(area) 使用裝飾器的這一步就相當於對area屬性指定了描述符,給Room2添加了一個類屬性 def area(self): return self.width * self.length r2 = Room(廚房, 10, 4) # 實例調用area print(r2.area) # 從r2中先找有沒有area屬性,沒有從父類Room2中找,找到後發現是非數據描述符,就觸發了__get__方法 # 類調用area print(Room2.area) # 由於__get__方法的接收參數需要一個實例,這裏是用類調用的,所以會傳None過去,因此會報錯

通過描述符自定制@property的功能