对象的三个装饰器@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

posted @ 2018-11-26 22:02  海予心  阅读(100)  评论(0编辑  收藏  举报