国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

讓Python中類的屬性具有惰性求值的能力

NervosNetwork / 1775人閱讀

摘要:更多描述可見文檔這種惰性求值的方法在很多模塊中都會使用,比如中的使用上與例子一致,如表單中的討論在大部分情況下,讓屬性具有惰性求值能力的全部意義就在于提升程序性能。當不需要這個屬性時就能避免進行無意義的計算,同時又能阻止該屬性重復進行計算。

起步

我們希望將一個只讀的屬性定義為 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 2.x 與 Python 3.x 的區別

    摘要:官方也宣布在停止對的維護。并且在很多面試過程中,面試官都會問與的區別。的版本,常被稱為,或簡稱。與部分地支持這種形式的語法。捕獲異常的語法由改為。在中,表示八進制字面量的方式只有一種,就是。已經支援新的模組。 前言 如果你是剛接觸 Python 的初學者,那你可能是直接學習 Python 3.x 版本。對于 Python 2.x 的版本是不會有所接觸。官方也宣布在 2020 停止對 P...

    LittleLiByte 評論0 收藏0
  • 函數范式入門(惰性求值與函數式狀態)

    摘要:純函數式狀態隨機數生成器很明顯,原有的函數不是引用透明的,這意味著它難以被測試組合并行化。售貨機在輸出糖果時忽略所有輸入本章知識點惰性求值函數式狀態 第二節?惰性求值與函數式狀態 在下面的代碼中我們對List數據進行了一些處理 List(1,2,3,4).map(_ + 10).filter(_ % 2 == 0).map(_ * 3) 考慮一下這段程序是如何求值的,如果我們跟蹤一下...

    Jrain 評論0 收藏0
  • 編程范式與函數式編程

    摘要:聲明式編程一種編程范式,與命令式編程相對立。常見的聲明式編程語言有數據庫查詢語言,正則表達式邏輯編程函數式編程組態管理系統等。函數式編程,特別是純函數式編程,嘗試最小化狀態帶來的副作用,因此被認為是聲明式的。 編程范式與函數式編程 一、編程范式的分類 常見的編程范式有:函數式編程、程序編程、面向對象編程、指令式編程等。在面向對象編程的世界,程序是一系列相互作用(方法)的對象(Class...

    noONE 評論0 收藏0
  • lazy.js 惰性求值實現分析

    摘要:同時還定義了接口,使得其下級可以從這里得到一個迭代器,對于該進行遍歷。迭代器在中也是一個約定的協議,實現該協議的對象要支持和兩個接口方法。從迭代器的邏輯中,可以看到,當對象作為其他的上級時,如果實現上傳下達。 背景:惰性求值? 來看一個 lazy.js 主頁提供的示例: var people = getBigArrayOfPeople(); var results = _.chain(...

    Forelax 評論0 收藏0
  • Flask-SQLAlchemy 學習總結

    摘要:初始化和配置對象關系映射。的則需要在中聲明。例如配置信息中指出是可以綁定多個數據庫引擎。是通過解決一對多的關系。將會返回學院學生人數將會返回學生的學院信息的類實例。處理關系對象查詢中有詳細的說明。 初始化和配置 ORM(Object Relational Mapper) 對象關系映射。指將面對對象得方法映射到數據庫中的關系對象中。Flask-SQLAlchemy是一個Flask擴展,能...

    whataa 評論0 收藏0

發表評論

0條評論

NervosNetwork

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<