摘要:更多描述可見文檔這種惰性求值的方法在很多模塊中都會使用,比如中的使用上與例子一致,如表單中的討論在大部分情況下,讓屬性具有惰性求值能力的全部意義就在于提升程序性能。當不需要這個屬性時就能避免進行無意義的計算,同時又能阻止該屬性重復進行計算。
起步
我們希望將一個只讀的屬性定義為 property 屬性方法,只有在訪問它時才進行計算,但是,又希望把計算出的值緩存起來,不要每次訪問它時都重新計算。
解決方案定義一個惰性屬性最有效的方法就是利用描述符類來完成它,示例如下:
class lazyproperty: def __init__(self, fun): self.fun = fun def __get__(self, instance, owner): if instance is None: return self value = self.fun(instance) setattr(instance, self.fun.__name__, value) return value
要使用這個工具,可以像下面的方式來使用它:
class Circle: def __init__(self, radius): self.radius = radius @lazyproperty def area(self): print("Computing area") return 3.1415 * self.radius ** 2 c = Circle(5) print(c.area) print(c.area)
可以看出,這里的實例方法 area() 只會被調用一次。
為什么會這樣如果類中定義了 __get__()、__set__() 、__delete__() 中的任何方法,那么這個就被成為描述符(descriptor)。
一般情況下(我是說一般情況下),訪問屬性的默認行為是從對象的字典中獲取,并沿著一個查找鏈的順序進行搜索,比如對于 a.x 有一個查找鏈,從 a.__dict__["x"] 然后是 type(a).__dict__["x"],再繼續通過 type(a) 的基類開始。
而如果查找的值是一個描述符對象,則會覆蓋這個默認的搜索行為,優先采用描述符的行為,這個行為會因為如果調用而有些不同。這里就只說明例子中的情況。
如果描述符綁定的對象實例,a.x 則轉換為調用: type(a).__dict__["x"].__get__(a, type(a))。
當一個描述符之定義 __get__() 方法,則它的綁定關系比一般情況下要弱化很多。特別是,只有當被訪問的屬性不存在對象字典中時,__get__() 才會被調用。
更多描述可見文檔:https://docs.python.org/3/ref...
這種惰性求值的方法在很多模塊中都會使用,比如django中的 cached_property:
使用上與例子一致,如表單中的 changed_data :
討論在大部分情況下,讓屬性具有惰性求值能力的全部意義就在于提升程序性能。當不需要這個屬性時就能避免進行無意義的計算,同時又能阻止該屬性重復進行計算。
本文的技巧中有一個潛在的缺點,就是計算出的值后就變成可變的(mutable)。
>>> c.area 78.53 >>> c.area = 3 >>> c.area 3
如果考慮可變性的問題,可以使用另一種實現方式,但執行效率會稍打折扣:
def lazyproperty(func): name = "_lazy_" + func.__name__ @property def lazy(self): if hasattr(self, name): return getattr(self, name) value = func(self) setattr(self, name, value) return value return lazy
如果使用這種方式,就會發現 set 操作是不允許的,所有的 get 操作都必須經由屬性的 getter 函數來處理,這比直接在實例字典中查找相應的值要慢一些。
參考https://docs.python.org/3/ref...
《Python Cookbook 第三版》
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42231.html
摘要:官方也宣布在停止對的維護。并且在很多面試過程中,面試官都會問與的區別。的版本,常被稱為,或簡稱。與部分地支持這種形式的語法。捕獲異常的語法由改為。在中,表示八進制字面量的方式只有一種,就是。已經支援新的模組。 前言 如果你是剛接觸 Python 的初學者,那你可能是直接學習 Python 3.x 版本。對于 Python 2.x 的版本是不會有所接觸。官方也宣布在 2020 停止對 P...
摘要:純函數式狀態隨機數生成器很明顯,原有的函數不是引用透明的,這意味著它難以被測試組合并行化。售貨機在輸出糖果時忽略所有輸入本章知識點惰性求值函數式狀態 第二節?惰性求值與函數式狀態 在下面的代碼中我們對List數據進行了一些處理 List(1,2,3,4).map(_ + 10).filter(_ % 2 == 0).map(_ * 3) 考慮一下這段程序是如何求值的,如果我們跟蹤一下...
摘要:聲明式編程一種編程范式,與命令式編程相對立。常見的聲明式編程語言有數據庫查詢語言,正則表達式邏輯編程函數式編程組態管理系統等。函數式編程,特別是純函數式編程,嘗試最小化狀態帶來的副作用,因此被認為是聲明式的。 編程范式與函數式編程 一、編程范式的分類 常見的編程范式有:函數式編程、程序編程、面向對象編程、指令式編程等。在面向對象編程的世界,程序是一系列相互作用(方法)的對象(Class...
摘要:同時還定義了接口,使得其下級可以從這里得到一個迭代器,對于該進行遍歷。迭代器在中也是一個約定的協議,實現該協議的對象要支持和兩個接口方法。從迭代器的邏輯中,可以看到,當對象作為其他的上級時,如果實現上傳下達。 背景:惰性求值? 來看一個 lazy.js 主頁提供的示例: var people = getBigArrayOfPeople(); var results = _.chain(...
摘要:初始化和配置對象關系映射。的則需要在中聲明。例如配置信息中指出是可以綁定多個數據庫引擎。是通過解決一對多的關系。將會返回學院學生人數將會返回學生的學院信息的類實例。處理關系對象查詢中有詳細的說明。 初始化和配置 ORM(Object Relational Mapper) 對象關系映射。指將面對對象得方法映射到數據庫中的關系對象中。Flask-SQLAlchemy是一個Flask擴展,能...
閱讀 466·2021-10-09 09:57
閱讀 470·2019-08-29 18:39
閱讀 811·2019-08-29 12:27
閱讀 3028·2019-08-26 11:38
閱讀 2667·2019-08-26 11:37
閱讀 1285·2019-08-26 10:59
閱讀 1376·2019-08-26 10:58
閱讀 989·2019-08-26 10:48