Detailed description of the property usage of the Python decorator

Source: Internet
Author: User
Tags python decorator
@property adorners can call a method into a property, so let's take a look at the Python black Magic @property. Analysis of the use technique of the decorator

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 the 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.radius print 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, 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.radius print c.area print c.area print C.area

As you can see, the ' Evalute ' is only output once, and the mechanism of @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:

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:

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, 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 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 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, 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

Class A:   pass >>type (a) <type ' classobj ' >
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.

Related Article

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.