对象的三个装饰器@classmethod、@staticmethod、@property
类中的三个装饰器方法
@classmethod、@staticmethod方法
类已经有普通方法(动态方法),为什么还要有可以这样理解,之所有@classmethod、@staticmethod方法,是因为python实行的是严格的范围管控机制,没有传参时就不必传类或对象给函数,以免提供给对外接口时,其他人利用函数对类和对象进行改动,同样的需要传类时也不能传对象,以免对外提供接口时,其他人对对象进行不应该有的操作。
class A: def __init__(self): pass def methoda(self): print('在普通方法中执行methoda') @classmethod def methoda(cls): print('在类方法中执行methoda') @staticmethod def methoda(): print('在静态方法中执行methoda') a=A() a.methoda() A.methoda() #调用普通方法时用A.methoda(参数) 执行结果: 在静态方法中执行methoda 在静态方法中执行methoda
@classmethod也会传一个默认参数cls,这地方要对比区分于普通方法的self,当用类名或对象名调用@classmethod的方法时,会自动传cls,不需要在单独传类名;@classmethod方法的默认参数都是类中的,不能是属于对象的
@staticmethod不需要传默认参数,通过 类名.类方法名 或 对象.类方法名 调用,它不能使用静态变量和对象变量
普通方法(动态方法)、@classmethod、@staticmethod均是定义在类中的方法,故他们均可通过对象或类调用,调用方法类似,差别在于不同方法中限定使用的变量不同(即传递的参数不同)
相同函数名分别用普通方法(动态方法)、@classmethod、@staticmethod写在同一函数中时,是采用从后到前一次查找的方式,先找到那个执行那个,实例代码中执行的是@staticmethod方法
@property方法
from math import pi class Circle: def __init__(self,r): self.r = r self.__perimeter = 2*pi*r @property def perimeter(self): return 2*pi*self.r @perimeter.setter def perimeter(self,new_r): self.__perimeter = 2*pi*new_r @perimeter.deleter def perimeter(self): del self.__perimeter c1 = Circle(5) print(c1.r,c1.perimeter) c1.r = 10 print(c1.r,c1.perimeter) c1.perimeter = 10 print(c1.perimeter) del c1.perimeter print(c1.perimeter)
执行结果:
5 31.41592653589793
10 62.83185307179586
62.83185307179586
62.83185307179586
@property一般是用来伪装私有属性,能够将私有属性伪装成一般属性,通过调用@property、@perimeter.setter、@perimeter.deleter实现查询、修改、删除属性功能,但此处要注意不能用@perimeter.setter修改一般属性(容易报递归最大深度错误),另外伪装属性可随一般属性的修改而修改,如实例代码中的属性r变化,__perimeter不会变化(在实例化的时候就已确定),但perimeter这个伪装属性却可以随着r的改变而改变
from math import pi class Circle: def __init__(self,r): self.r = r self.perimeter = 2*pi*r @property def perimeter2(self): return 2*pi*self.r @perimeter2.setter def perimeter2(self,new_r): self.perimeter2 = 2*pi*new_r # @perimeter2.deleter # def perimeter2(self): # del self.perimeter2 c1 = Circle(5) print(c1.r,c1.perimeter,c1.perimeter2) c1.r = 10 print(c1.r,c1.perimeter,c1.perimeter2) c1.perimeter2 = 8 print(c1.perimeter2) # del c1.perimeter2 # print(c1.perimeter2) 执行结果: RecursionError: maximum recursion depth exceeded