摘要:更多描述可見(jiàn)文檔這種惰性求值的方法在很多模塊中都會(huì)使用,比如中的使用上與例子一致,如表單中的討論在大部分情況下,讓屬性具有惰性求值能力的全部意義就在于提升程序性能。當(dāng)不需要這個(gè)屬性時(shí)就能避免進(jìn)行無(wú)意義的計(jì)算,同時(shí)又能阻止該屬性重復(fù)進(jìn)行計(jì)算。
起步
我們希望將一個(gè)只讀的屬性定義為 property 屬性方法,只有在訪問(wèn)它時(shí)才進(jìn)行計(jì)算,但是,又希望把計(jì)算出的值緩存起來(lái),不要每次訪問(wèn)它時(shí)都重新計(jì)算。
解決方案定義一個(gè)惰性屬性最有效的方法就是利用描述符類來(lái)完成它,示例如下:
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
要使用這個(gè)工具,可以像下面的方式來(lái)使用它:
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)
可以看出,這里的實(shí)例方法 area() 只會(huì)被調(diào)用一次。
為什么會(huì)這樣如果類中定義了 __get__()、__set__() 、__delete__() 中的任何方法,那么這個(gè)就被成為描述符(descriptor)。
一般情況下(我是說(shuō)一般情況下),訪問(wèn)屬性的默認(rèn)行為是從對(duì)象的字典中獲取,并沿著一個(gè)查找鏈的順序進(jìn)行搜索,比如對(duì)于 a.x 有一個(gè)查找鏈,從 a.__dict__["x"] 然后是 type(a).__dict__["x"],再繼續(xù)通過(guò) type(a) 的基類開(kāi)始。
而如果查找的值是一個(gè)描述符對(duì)象,則會(huì)覆蓋這個(gè)默認(rèn)的搜索行為,優(yōu)先采用描述符的行為,這個(gè)行為會(huì)因?yàn)槿绻{(diào)用而有些不同。這里就只說(shuō)明例子中的情況。
如果描述符綁定的對(duì)象實(shí)例,a.x 則轉(zhuǎn)換為調(diào)用: type(a).__dict__["x"].__get__(a, type(a))。
當(dāng)一個(gè)描述符之定義 __get__() 方法,則它的綁定關(guān)系比一般情況下要弱化很多。特別是,只有當(dāng)被訪問(wèn)的屬性不存在對(duì)象字典中時(shí),__get__() 才會(huì)被調(diào)用。
更多描述可見(jiàn)文檔:https://docs.python.org/3/ref...
這種惰性求值的方法在很多模塊中都會(huì)使用,比如django中的 cached_property:
使用上與例子一致,如表單中的 changed_data :
討論在大部分情況下,讓屬性具有惰性求值能力的全部意義就在于提升程序性能。當(dāng)不需要這個(gè)屬性時(shí)就能避免進(jìn)行無(wú)意義的計(jì)算,同時(shí)又能阻止該屬性重復(fù)進(jìn)行計(jì)算。
本文的技巧中有一個(gè)潛在的缺點(diǎn),就是計(jì)算出的值后就變成可變的(mutable)。
>>> c.area 78.53 >>> c.area = 3 >>> c.area 3
如果考慮可變性的問(wèn)題,可以使用另一種實(shí)現(xiàn)方式,但執(zhí)行效率會(huì)稍打折扣:
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
如果使用這種方式,就會(huì)發(fā)現(xiàn) set 操作是不允許的,所有的 get 操作都必須經(jīng)由屬性的 getter 函數(shù)來(lái)處理,這比直接在實(shí)例字典中查找相應(yīng)的值要慢一些。
參考https://docs.python.org/3/ref...
《Python Cookbook 第三版》
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42231.html
摘要:官方也宣布在停止對(duì)的維護(hù)。并且在很多面試過(guò)程中,面試官都會(huì)問(wèn)與的區(qū)別。的版本,常被稱為,或簡(jiǎn)稱。與部分地支持這種形式的語(yǔ)法。捕獲異常的語(yǔ)法由改為。在中,表示八進(jìn)制字面量的方式只有一種,就是。已經(jīng)支援新的模組。 前言 如果你是剛接觸 Python 的初學(xué)者,那你可能是直接學(xué)習(xí) Python 3.x 版本。對(duì)于 Python 2.x 的版本是不會(huì)有所接觸。官方也宣布在 2020 停止對(duì) P...
摘要:純函數(shù)式狀態(tài)隨機(jī)數(shù)生成器很明顯,原有的函數(shù)不是引用透明的,這意味著它難以被測(cè)試組合并行化。售貨機(jī)在輸出糖果時(shí)忽略所有輸入本章知識(shí)點(diǎn)惰性求值函數(shù)式狀態(tài) 第二節(jié)?惰性求值與函數(shù)式狀態(tài) 在下面的代碼中我們對(duì)List數(shù)據(jù)進(jìn)行了一些處理 List(1,2,3,4).map(_ + 10).filter(_ % 2 == 0).map(_ * 3) 考慮一下這段程序是如何求值的,如果我們跟蹤一下...
摘要:聲明式編程一種編程范式,與命令式編程相對(duì)立。常見(jiàn)的聲明式編程語(yǔ)言有數(shù)據(jù)庫(kù)查詢語(yǔ)言,正則表達(dá)式邏輯編程函數(shù)式編程組態(tài)管理系統(tǒng)等。函數(shù)式編程,特別是純函數(shù)式編程,嘗試最小化狀態(tài)帶來(lái)的副作用,因此被認(rèn)為是聲明式的。 編程范式與函數(shù)式編程 一、編程范式的分類 常見(jiàn)的編程范式有:函數(shù)式編程、程序編程、面向?qū)ο缶幊獭⒅噶钍骄幊痰?。在面向?qū)ο缶幊痰氖澜?,程序是一系列相互作用(方法)的?duì)象(Class...
摘要:同時(shí)還定義了接口,使得其下級(jí)可以從這里得到一個(gè)迭代器,對(duì)于該進(jìn)行遍歷。迭代器在中也是一個(gè)約定的協(xié)議,實(shí)現(xiàn)該協(xié)議的對(duì)象要支持和兩個(gè)接口方法。從迭代器的邏輯中,可以看到,當(dāng)對(duì)象作為其他的上級(jí)時(shí),如果實(shí)現(xiàn)上傳下達(dá)。 背景:惰性求值? 來(lái)看一個(gè) lazy.js 主頁(yè)提供的示例: var people = getBigArrayOfPeople(); var results = _.chain(...
摘要:初始化和配置對(duì)象關(guān)系映射。的則需要在中聲明。例如配置信息中指出是可以綁定多個(gè)數(shù)據(jù)庫(kù)引擎。是通過(guò)解決一對(duì)多的關(guān)系。將會(huì)返回學(xué)院學(xué)生人數(shù)將會(huì)返回學(xué)生的學(xué)院信息的類實(shí)例。處理關(guān)系對(duì)象查詢中有詳細(xì)的說(shuō)明。 初始化和配置 ORM(Object Relational Mapper) 對(duì)象關(guān)系映射。指將面對(duì)對(duì)象得方法映射到數(shù)據(jù)庫(kù)中的關(guān)系對(duì)象中。Flask-SQLAlchemy是一個(gè)Flask擴(kuò)展,能...
閱讀 483·2021-10-09 09:57
閱讀 486·2019-08-29 18:39
閱讀 824·2019-08-29 12:27
閱讀 3039·2019-08-26 11:38
閱讀 2680·2019-08-26 11:37
閱讀 1305·2019-08-26 10:59
閱讀 1391·2019-08-26 10:58
閱讀 998·2019-08-26 10:48