關于@property裝飾器
在Python中我們使用@property裝飾器來把對函數的調用偽裝成對屬性的訪問。
那么為什么要這樣做呢?因為@property讓我們將自定義的代碼同變量的訪問/設定聯系在了一起,同時為你的類保持一個簡單的訪問屬性的接口。
舉個栗子,假如我們有一個需要表示電影的類:
class Movie(object): def __init__(self, title, description, score, ticket): self.title = title self.description = description self.score = scroe self.ticket = ticket
你開始在項目的其他地方使用這個類,但是之后你意識到:如果不小心給電影打了負分怎么辦?你覺得這是錯誤的行為,希望Movie類可以阻止這個錯誤。 你首先想到的辦法是將Movie類修改為這樣:
class Movie(object): def __init__(self, title, description, score, ticket): self.title = title self.description = description self.ticket = ticket if score < 0: raise ValueError("Negative value not allowed:{}".format(score)) self.score = scroe但這行不通。因為其他部分的代碼都是直接通過Movie.score來賦值的。這個新修改的類只會在__init__方法中捕獲錯誤的數據,但對于已經存在的類實例就無能為力了。如果有人試著運行m.scrore= -100,那么誰也沒法阻止。那該怎么辦?
Python的property解決了這個問題。
我們可以這樣做
class Movie(object): def __init__(self, title, description, score): self.title = title self.description = description self.score = score self.ticket = ticket @property def score(self): return self.__score @score.setter def score(self, score): if score < 0: raise ValueError("Negative value not allowed:{}".format(score)) self.__score = score @score.deleter def score(self): raise AttributeError("Can not delete score")這樣在任何地方修改score都會檢測它是否小于0。
property的不足
對property來說,最大的缺點就是它們不能重復使用。舉個例子,假設你想為ticket字段也添加非負檢查。
下面是修改過的新類:
class Movie(object): def __init__(self, title, description, score, ticket): self.title = title self.description = description self.score = score self.ticket = ticket @property def score(self): return self.__score @score.setter def score(self, score): if score < 0: raise ValueError("Negative value not allowed:{}".format(score)) self.__score = score @score.deleter def score(self): raise AttributeError("Can not delete score") @property def ticket(self): return self.__ticket @ticket.setter def ticket(self, ticket): if ticket < 0: raise ValueError("Negative value not allowed:{}".format(ticket)) self.__ticket = ticket @ticket.deleter def ticket(self): raise AttributeError("Can not delete ticket")可以看到代碼增加了不少,但重復的邏輯也出現了不少。雖然property可以讓類從外部看起來接口整潔漂亮,但是卻做不到內部同樣整潔漂亮。
描述符登場
什么是描述符?
一般來說,描述符是一個具有綁定行為的對象屬性,其屬性的訪問被描述符協議方法覆寫。這些方法是__get__() 、 __set__()和__delete__() ,一個對象中只要包含了這三個方法中的至少一個就稱它為描述符。
描述符有什么作用?
The default behavior for attribute access is to get, set, or delete the attribute from an object's dictionary. For instance, a.x has a lookup chain starting witha.__dict__[‘x'], then type(a).__dict__[‘x'], and continuing through the base classes of type(a) excluding metaclasses. If the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. Where this occurs in the precedence chain depends on which descriptor methods were defined.― 主站蜘蛛池模板: 东乡| 宁安市| 和平区| 惠来县| 荃湾区| 安阳市| 牟定县| 格尔木市| 德阳市| 临颍县| 从化市| 潞西市| 桑日县| 应城市| 都江堰市| 海晏县| 延川县| 治县。| 汾阳市| 公主岭市| 泰宁县| 固安县| 商丘市| 安顺市| 乌苏市| 朝阳县| 辉县市| 沂水县| 麻城市| 洪洞县| 繁昌县| 临泉县| 海门市| 石柱| 望城县| 银川市| 镇远县| 涿鹿县| 东阳市| 昔阳县| 务川|