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.