日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
創(chuàng)新互聯(lián)Python教程:Python黑魔法之property裝飾器詳解

@Property裝飾器能把一個(gè)方法變成屬性一樣來(lái)調(diào)用,下面我們就一起來(lái)看看Python黑魔法@property裝飾器的使用技巧解析

創(chuàng)新互聯(lián)建站是一家專業(yè)提供滕州企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、H5響應(yīng)式網(wǎng)站、小程序制作等業(yè)務(wù)。10年已為滕州眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進(jìn)行中。

@property有什么用呢?表面看來(lái),就是將一個(gè)方法用屬性的方式來(lái)訪問(wèn).

上代碼,代碼最清晰了.

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雖然是定義成一個(gè)方法的形式,但是加上@property后,可以直接c.area,當(dāng)成屬性訪問(wèn).

現(xiàn)在問(wèn)題來(lái)了,每次調(diào)用c.area,都會(huì)計(jì)算一次,太浪費(fèi)cpu了,怎樣才能只計(jì)算一次呢?這就是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'只輸出了一次,對(duì)@lazy的機(jī)制應(yīng)該很好理解.

在這里,lazy類有__get__方法,說(shuō)明是個(gè)描述器,第一次執(zhí)行c.area的時(shí)候,因?yàn)轫樞騿?wèn)題,先去c.__dict__中找,沒(méi)找到,就去類空間找,在類Circle中,有area()方法,于是就被__get__攔截.

在__get__中,調(diào)用實(shí)例的area()方法算出結(jié)果,并動(dòng)態(tài)給實(shí)例添加個(gè)同名屬性把結(jié)果賦給它,即加到c.__dict__中去.

再次執(zhí)行c.area的時(shí)候,先去c.__dict__找,因?yàn)榇藭r(shí)已經(jīng)有了,就不會(huì)經(jīng)過(guò)area()方法和__get__了.

注意點(diǎn)

請(qǐng)注意以下代碼場(chǎng)景:

代碼片段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的區(qū)別在于 

class Parrot(object):

在python2下,分別運(yùn)行測(cè)試

片段1:將會(huì)提示一個(gè)預(yù)期的錯(cuò)誤信息 AttributeError: can't set attribute

片段2:正確運(yùn)行

參考python2文檔,@property將提供一個(gè)ready-only property,以上代碼沒(méi)有提供對(duì)應(yīng)的@voltage.setter,按理說(shuō)片段2代碼將提示運(yùn)行錯(cuò)誤,在python2文檔中,我們可以找到以下信息:

BIF: 

property([fget[, fset[, fdel[, doc]]]])

Return a property attribute for new-style classes (classes that derive from object).

原來(lái)在python2下,內(nèi)置類型 object 并不是默認(rèn)的基類,如果在定義類時(shí),沒(méi)有明確說(shuō)明的話(代碼片段2),我們定義的Parrot(代碼片段2)將不會(huì)繼承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__().

同時(shí)我們也可以通過(guò)以下方法來(lái)驗(yàn)證

class A: 
  pass 
>>type(A) 
class A(object): 
  pass 
>>type(A) 

從返回的可以看出是我們需要的object類型(python 3.0 將object類作為默認(rèn)基類,所以都將返回

為了考慮代碼的python 版本過(guò)渡期的兼容性問(wèn)題,我覺(jué)得應(yīng)該定義class文件的時(shí)候,都應(yīng)該顯式定義object,做為一個(gè)好習(xí)慣

最后的代碼將如下

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沒(méi)有該功能。


網(wǎng)站名稱:創(chuàng)新互聯(lián)Python教程:Python黑魔法之property裝飾器詳解
網(wǎng)站網(wǎng)址:http://www.5511xx.com/article/cdijohd.html