欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python黑魔法@property裝飾器的使用技巧解析

 更新時間:2016年06月16日 15:30:58   作者:mattkang  
@property裝飾器能把一個方法變成屬性一樣來調用,下面我們就一起來看看Python黑魔法@property裝飾器的使用技巧解析

@property有什么用呢?表面看來,就是將一個方法用屬性的方式來訪問.
上代碼,代碼最清晰了.

class Circle(object): 
  def __init__(self, radius): 
    self.radius = radius 
 
  @property 
  def area(self): 
    return 3.14 * self.radius ** 2 
 
c = Circle(4) 
print c.radius 
print c.area 

可以看到,area雖然是定義成一個方法的形式,但是加上@property后,可以直接c.area,當成屬性訪問.
現在問題來了,(不是挖掘機技術哪家強),每次調用c.area,都會計算一次,太浪費cpu了,怎樣才能只計算一次呢?這就是lazy property.

class lazy(object): 
  def __init__(self, func): 
    self.func = func 
 
  def __get__(self, instance, cls): 
    val = self.func(instance) 
    setattr(instance, self.func.__name__, val) 
    return val 
 
class Circle(object): 
  def __init__(self, radius): 
    self.radius = radius 
 
  @lazy 
  def area(self): 
    print 'evalute' 
    return 3.14 * self.radius ** 2 
 
c = Circle(4) 
print c.radius 
print c.area 
print c.area 
print c.area 

可以看到,'evalute'只輸出了一次.如果看了我前面幾篇博文,對@lazy的機制應該很好理解.
在這里,lazy類有__get__方法,說明是個描述器,第一次執(zhí)行c.area的時候,因為順序問題,先去c.__dict__中找,沒找到,就去類空間找,在類Circle中,有area()方法,于是就被__get__攔截.
在__get__中,調用實例的area()方法算出結果,并動態(tài)給實例添加個同名屬性把結果賦給它,即加到c.__dict__中去.
再次執(zhí)行c.area的時候,先去c.__dict__找,因為此時已經有了,就不會經過area()方法和__get__了.

注意點
請注意以下代碼場景:

代碼片段1:
Python2.6代碼 

class Parrot(object): 
  def __init__(self): 
    self._voltage = 100000 
 
  @property 
  def voltage(self): 
    """Get the current voltage.""" 
    return self._voltage 
 
if __name__ == "__main__": 
  # instance 
  p = Parrot() 
  # similarly invoke "getter" via @property 
  print p.voltage 
  # update, similarly invoke "setter" 
  p.voltage = 12 

代碼片段2:
Python2.6代碼 

class Parrot: 
  def __init__(self): 
    self._voltage = 100000 
 
  @property 
  def voltage(self): 
    """Get the current voltage.""" 
    return self._voltage 
 
if __name__ == "__main__": 
  # instance 
  p = Parrot() 
  # similarly invoke "getter" via @property 
  print p.voltage 
  # update, similarly invoke "setter" 
  p.voltage = 12 

代碼1、2的區(qū)別在于

class Parrot(object): 

在python2.6下,分別運行測試
片段1:將會提示一個預期的錯誤信息 AttributeError: can't set attribute
片段2:正確運行

參考python2.6文檔,@property將提供一個ready-only property,以上代碼沒有提供對應的@voltage.setter,按理說片段2代碼將提示運行錯誤,在python2.6文檔中,我們可以找到以下信息:

BIF:
property([fget[, fset[, fdel[, doc]]]])
Return a property attribute for new-style classes (classes that derive from object).
原來在python2.6下,內置類型 object 并不是默認的基類,如果在定義類時,沒有明確說明的話(代碼片段2),我們定義的Parrot(代碼片段2)將不會繼承object

而object類正好提供了我們需要的@property功能,在文檔中我們可以查到如下信息:

new-style class
Any class which inherits from object. This includes all built-in types like list and dict. Only new-style classes can use Python's newer, versatile features like __slots__, descriptors, properties, and __getattribute__().

同時我們也可以通過以下方法來驗證
Python 2.6代碼 

class A: 
  pass 

>>type(A) 
<type 'classobj'> 

Python 2.6代碼 

class A(object): 
  pass 

>>type(A) 
<type 'type'> 

從返回的<type 'classobj'>,<type 'type'>可以看出<type 'type'>是我們需要的object類型(python 3.0 將object類作為默認基類,所以都將返回<type 'type'>)

為了考慮代碼的python 版本過渡期的兼容性問題,我覺得應該定義class文件的時候,都應該顯式定義object,做為一個好習慣

最后的代碼將如下:

class Parrot(object): 
  def __init__(self): 
    self._voltage = 100000 

  @property 
  def voltage(self): 
    """Get the current voltage.""" 
    return self._voltage 

  @voltage.setter 
  def voltage(self, new_value): 
    self._voltage = new_value 
 
if __name__ == "__main__": 
  # instance 
  p = Parrot() 
  # similarly invoke "getter" via @property 
  print p.voltage 
  # update, similarly invoke "setter" 
  p.voltage = 12 

另外,@property是在2.6、3.0新增的,2.5沒有該功能。

相關文章

  • Python實現繁體轉為簡體的方法示例

    Python實現繁體轉為簡體的方法示例

    這篇文章主要介紹了Python實現繁體轉為簡體的方法,涉及Python編碼轉換相關操作技巧,需要的朋友可以參考下
    2018-12-12
  • Python機器學習NLP自然語言處理基本操作之命名實例提取

    Python機器學習NLP自然語言處理基本操作之命名實例提取

    自然語言處理(?Natural?Language?Processing,?NLP)是計算機科學領域與人工智能領域中的一個重要方向。它研究能實現人與計算機之間用自然語言進行有效通信的各種理論和方法
    2021-11-11
  • Python request post上傳文件常見要點

    Python request post上傳文件常見要點

    這篇文章主要介紹了Python request post上傳文件常見要點,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • Python實現在圖像中隱藏二維碼的方法詳解

    Python實現在圖像中隱藏二維碼的方法詳解

    隱寫是一種類似于加密卻又不同于加密的技術。這篇文章主要介紹了如何利用Python語言實現在圖像中隱藏二維碼功能,感興趣的可以了解一下
    2022-09-09
  • django使用channels實現通信的示例

    django使用channels實現通信的示例

    這篇文章主要介紹了django使用channels實現通信的示例,幫助大家更好的理解和學習django框架,感興趣的朋友可以了解下
    2020-10-10
  • Pytest單元測試框架如何實現參數化

    Pytest單元測試框架如何實現參數化

    這篇文章主要介紹了Pytest單元測試框架如何實現參數化,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • python requests.post帶head和body的實例

    python requests.post帶head和body的實例

    今天小編就為大家分享一篇python requests.post帶head和body的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • 如何利用pytesseract識別圖片中的數字

    如何利用pytesseract識別圖片中的數字

    這篇文章主要介紹了如何利用pytesseract識別圖片中的數字問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • python多進程提取處理大量文本的關鍵詞方法

    python多進程提取處理大量文本的關鍵詞方法

    今天小編就為大家分享一篇python多進程提取處理大量文本的關鍵詞方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Pycharm2022最新版無法換源解決方法

    Pycharm2022最新版無法換源解決方法

    本文主要介紹了Pycharm2022最新版無法換源解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02

最新評論