Python black Magic @property The use of the Decoration device analysis

Source: Internet
Author: User
What's the use of @property? On the surface, it is to access a method in the form of a property.
Code, the code is clearest.

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.radiusprint C.area

As you can see, area is defined as a form of a method, but with @property, you can directly C.area, as a property access.
Now the problem, (not the excavator technology which strong), every call C.area, will be calculated once, too wasted CPU, how to calculate only once? This is the 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.radiusprint c.areaprint c.areaprint C.area

As you can see, ' evalute ' is only output once. If you look at my previous posts, the mechanism for @lazy should be well understood.
Here, the lazy class has the __get__ method, the description is a descriptor, the first time to execute C.area, because the order problem, first go to c.__dict__, did not find, go to class space to find, in the class circle, there is area () method, so it was __get__ intercept.
In __get__, the area () method of the calling instance calculates the result, and dynamically adds a property of the same name to the instance, assigning the result to it, which is added to the c.__dict__.
Execute C.area again, first go to c.__dict__ find, because at this time already have, will not go through area () method and __get__.

Watch out.
Please note the following code scenario:

Code Snippet 1:
Python2.6 Code

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 @p Roperty  Print p.voltage  # Update, similarly invoke "setter"  P.voltage = 12

Code Snippet 2:
Python2.6 Code

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" V IA @property  print p.voltage  # Update, similarly invoke "setter"  P.voltage = 12

The difference between code 1 and 2 is that

Class Parrot (object):

Under python2.6, run the tests separately
Fragment 1: An expected error message will be prompted Attributeerror:can ' t set attribute
Fragment 2: Run correctly

Refer to the python2.6 documentation, @property will provide a ready-only property, The above code does not provide the corresponding @voltage.setter, supposedly the fragment 2 code will prompt to run the error, in the python2.6 document, we can find the following information:

BIF:
Property ([Fget[, fset[, fdel[, Doc]])
Return a property attribute for New-style classes (classes, derive from object).
Originally under python2.6, the built-in type object is not the default base class, and if there is no explicit explanation when defining the class (Code Snippet 2), the Parrot (Code Snippet 2) We define will not inherit the object

The object class provides exactly the @property functionality we need, and in the documentation we can find the following information:

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 __getattrib UTE__ ().

At the same time, we can also use the following methods to verify
Python 2.6 Code

Class A:  pass >>type (a) <type ' classobj ' >

Python 2.6 Code

Class A (object):  pass >>type (a) <type ' type ' >

From the returned <type ' classobj ' >,<type ' type ' > you can see that <type ' type ' > is the type of object we need (Python 3.0 takes the object class as the default base class, So all will return <type ' type ' >)

In order to consider the compatibility of the Python version of the code in the transition period, I think the class file should be defined when it should be explicitly defined as an object, as a good habit

The final code will look like this:

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.volta GE  # Update, similarly invoke "setter"  P.voltage = 12

In addition, the @property is new in 2.6, 3.0, 2.5 does not have this feature.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.