Reprinted from https://www.cnblogs.com/wangyongsong/p/6750454.html
1. Properties
1 What is a feature property
A property is a special property that, when accessed, executes a piece of functionality (function) and returns a value
1 import math 2 class Circle: 3 def __init__(self,radius): #The radius of the circle radius 4 self.radius=radius 5 6 @property 7 def area(self): 8 return math.pi * self.radius**2 #Calculate area 9 10 @property 11 def perimeter(self): 12 return 2*math.pi*self.radius #Calculate the circumference 13 14 c=Circle(10) 15 print(c.radius) 16 print(c.area) #You can access area like accessing data attributes, which will trigger the execution of a function and dynamically calculate a value 17 print(c.perimeter) #Same as above 18 ''' 19 Output result: 20 314.1592653589793 21 62.83185307179586 22 '''
Note: The features arear and perimeter cannot be assigned at this time
c.area=3 #Assign the feature area ''' Throw an exception: AttributeError: can't set attribute '''
2 Why use property
After defining the function of a class as a feature, when the object uses obj.name again, it is impossible to notice that its name is calculated by executing a function. The use of this feature follows the principle of unified access.
Besides, see
ps: There are three ways of object-oriented encapsulation: 【public】 This is actually not encapsulated, it is open to the public 【protected】 This encapsulation method is not open to the public, but for friends or subclasses (the image is called "son", but I don't know why people don't say "daughter", just like "parent" originally means "parent" , but Chinese are called "parent class") public 【private】 This encapsulation is not open to anyone
Python does not syntactically build the three of them into its own class mechanism. In C++, all data is generally set as private, and then set and get methods (interfaces) are provided to set and obtain, This can be achieved by the property method in python
1 class Foo: 2 def __init__(self,val): 3 self.__NAME=val #Hide all data attributes 4 5 @property 6 def name(self): 7 return self.__NAME #obj.name accesses self.__NAME (this is also where the real value is stored) 8 9 @name.setter 10 def name(self,value): 11 if not isinstance(value,str): #Type check before setting value 12 raise TypeError('%s must be str' %value) 13 self.__NAME=value #After passing the type check, store the value value in the real location self.__NAME 14 15 @name.deleter 16 def name(self): 17 raise TypeError('Can not delete') 18 19 f=Foo('egon') 20 print(f.name) 21 # f.name=10 #Throw exception 'TypeError: 10 must be str' 22 del f.name #Throw exception 'TypeError: Can not delete'
Two, static method (staticmethod)
Under normal circumstances, all functions defined in a class (note that it is all here, it has nothing to do with self, self is just a common parameter) are the binding methods of the object, and the object is calling the binding method. When defining a method, it automatically passes itself as a parameter to the first parameter of the method. In addition to this, there are two common methods: static methods and class methods, both of which are tailored for classes, but instances must be used and no errors will be reported.
It is an ordinary function, located in the namespace defined by the class, and will not operate on any instance type. Python has built-in the function staticmethod for us to define the functions in the class as static methods.
class Foo: def spam(x,y,z): #A function in the class, don't be fooled, there is no difference between self and x, they are all parameter names print(x,y,z) spam=staticmethod(spam) #Make the spam function a static method
Based on the knowledge of decorators learned before, @staticmethod is equivalent to spam=staticmethod(spam), so
class Foo: @staticmethod #Decorator def spam(x,y,z): print(x,y,z)
use demo
print(type(Foo.spam)) #The essence of the type is the function Foo.spam(1,2,3) #The calling function should have several parameters and pass several parameters f1=Foo() f1.spam(3,3,3) #Instances can also be used, but usually static methods are used for classes, and instances lose the mechanism of automatic value transfer when they are used. ''' <class 'function'> 2 3 3 3 '''
Application scenario: There are many different ways to create instances when writing a class, and we only have one __init__ function, at which point static methods come in handy
class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): #Use Date.now() to generate an instance, which uses the current time t=time.localtime() #Get the structured time format return Date(t.tm_year,t.tm_mon,t.tm_mday) #Create an instance and return @staticmethod def tomorrow(): #Use Date.tomorrow() to generate an instance, which uses tomorrow's time t=time.localtime(time.time()+86400) return Date(t.tm_year,t.tm_mon,t.tm_mday) a=Date('1987',11,27) #Define the time yourself b=Date.now() #Use the current time c=Date.tomorrow() #Use tomorrow's time print(a.year,a.month,a.day) print(b.year,b.month,b.day) print(c.year,c.month,c.day)
Three, class method (classmethod)
The class method is for the class. When the class is used, it will pass the class itself as a parameter to the first parameter of the class method (the first parameter will only pass the instance of the class without @classmethod), python has built-in functions for us classmethod to define a function in a class as a class method
class A: x=1 @classmethod def test(cls): print(cls,cls.x) class B(A): x=2 B.test() #If you replace it with @staticmethod, it will report an error that a cls parameter is missing ''' Output result: <class '__main__.B'> 2 '''
Application scenarios:
import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): t=time.localtime() return Date(t.tm_year,t.tm_mon,t.tm_mday) class EuroDate(Date): def __str__(self): return 'year:%s month:%s day:%s' %(self.year,self.month,self.day) e=EuroDate.now() print(e) #Our intention is to trigger EuroDate.__str__, but the result is ''' Output result: <__main__.Date object at 0x1013f9d68> '''
Because e is generated by the Date class, EuroDate.__str__ will not be triggered at all. The solution is to use classmethod
import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day # @staticmethod # def now(): # t=time.localtime() # return Date(t.tm_year,t.tm_mon,t.tm_mday) @classmethod #Change to class method def now(cls): t=time.localtime() return cls(t.tm_year, t.tm_mon, t.tm_mday) #Which class to call, that is, which class cls is used to instantiate class EuroDate(Date): def __str__(self): return 'year:%s month:%s day:%s' %(self.year,self.month,self.day) e=EuroDate.now() print(e) #Our intention is to trigger EuroDate.__str__, at this time e is generated by EuroDate, so it will be as we wish ''' Output result: year:2017 month:3 day:3 '''
Emphasize, pay attention: Although static methods and class methods are prepared for classes, they can also be used if they are used by instances, but it is easy to confuse people when they are called by instances. I don't know what you want to do.
x=e.now() #Calling class methods through instance e can also be used, as can static methods print(x) ''' Output result: year:2017 month:3 day:3 '''
Fourth, the usage of additional knowledge points __str__
#__str__ is defined inside the class and must return a string type, #When will it start its execution? Execution is triggered when an object produced by this class is printed class People: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return '<name:%s,age:%s>' %(self.name,self.age) p1=People('egon',18) print(p1) str (p1) # -----> p1 .__ str __ ()