python装饰器 property_Python中@property装饰器的使用技巧性解析(代码示例)
Python中@property裝飾器的技巧性用法(代碼示例)
本篇文章給大家帶來的內容是關于Python中@property裝飾器的技巧性用法(代碼示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。
@property裝飾器能把一個方法變成屬性一樣來調用,下面我們就一起來看看Python的黑魔法@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
可以看到,面積雖然是定義成一個方法的形式,但是加上@財產后,可以直接c.area,當成屬性訪問。
現在問題來了,每次調用c.area,都會計算一次,太浪費cpu了,怎樣才能只計算一次呢?這就是懶惰的財產。
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的機制應該很好理解。
在這里,懶惰類有__get__方法,說明是個描述器,第一次執行c.area的時候,因為順序問題,先去?.__ dict__中找,沒找到,就去類空間找,在類圈中,有面積()方法,于是就被__get__攔截。
在__get__中,調用實例的區域()方法算出結果,并動態給實例添加個同名屬性把結果賦給它,即加到?.__ dict__中去。
再次執行c.area的時候,先去?.__ dict__找,因為此時已經有了,就不會經過區域()方法和__get__了。
注意點
請注意以下代碼場景:
代碼片段1:
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:
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的區別在于
class Parrot(對象):
在python2下,分別運行測試
片段1:將會提示一個預期的錯誤信息AttributeError:無法設置屬性
片段2:正確運行
參考python2文檔,@ property將提供一個ready-only屬性,以上代碼沒有提供對應的@ voltage.setter,按理說片段2代碼將提示運行錯誤,在python2文檔中,我們可以找到以下信息:
BIF:
property([fget [,fset [,fdel [,doc]]]])
返回新樣式類的屬性屬性(從對象派生的類)。
原來在python2下,內置類型對象并不是默認的基類,如果在定義類時,沒有明確說明的話(代碼片段2),我們定義的Parrot(代碼片段2)將不會繼承對象
而對象類正好提供了我們需要的@property功能,在文檔中我們可以查到如下信息:
新式課
任何繼承自object的類。這包括所有內置類型,如list和dict。只有新式類可以使用Python的更新,通用的功能,如__slots__,描述符,屬性和__getattribute __()。
同時我們也可以通過以下方法來驗證
class A:
pass
>>type(A)
class A(object):
pass
>>type(A)
從返回的,可以看出是我們需要的對象類型(python 3.0將對象類作為默認基類,所以都將返回)
為了考慮代碼的python版本過渡期的兼容性問題,我覺得應該定義類文件的時候,都應該顯式定義對象,做為一個好習慣
最后的代碼將如下:
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
以上就是Python中@property裝飾器的技巧性用法(代碼示例)的詳細內容,更多請關注碼農之家其它相關文章!
以上就是本次給大家分享的關于java的全部知識點內容總結,大家還可以在下方相關文章里找到相關文章進一步學習,感謝大家的閱讀和支持。
總結
以上是生活随笔為你收集整理的python装饰器 property_Python中@property装饰器的使用技巧性解析(代码示例)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 应用程序池超出其作业限制设置_网站改版注
- 下一篇: pc双网卡实现路由转发_route命令如