@staticmethod && @classmethod && @property

未完待续。。。。。。

3. python内置的函数装饰器

   有3种,分别是 @staticmethod、@classmethod 和 @property。

   其中 staticmethod()、classmethod() 和 property() 都是 Python 的内置函数。

   - 先解释下python中的类变量(或叫做静态变量),它定义在类中的位置如下:

class Test:
    stc_attr = 1         # 类变量
    def __init__(self,attr1,attr2):
     self.attr1 = attr1
        self.attr2 = attr2

   1)staticmethod 是类的静态方法:其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用,也可以在实例化的情况使用。

      由于静态方法不包含 self 参数,所以它只能通过类名访问类的静态成员变量和静态成员函数,如 类名.属性名、类名.方法名。

      注:如果不通过类名访问静态成员变量,那其实是重新定义了一个变量。不通过类名访问静态成员函数,会提示函数无定义。

class Test(object):
    x = 0.1
    @staticmethod
    def f():
        print("call static method.")
        Test.x = 0.5

Test.f()       # 静态方法无需实例化
Test().f()     # 也可以实例化后调用
print(Test.x)

"""
output:
call static method.
call static method.
0.5
"""  

   2)classmethod 是类方法:与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型,有子类继承时,就是子类类型)。

      其使用语法和staticmethod方法一致。但静态方法的行为就是一个普通的全局函数,而类方法包含cls参数,那cls参数有啥用呢?

      解释:比如静态方法想要调用非静态的成员,必须知道类的具体类型,然后在函数内部构造一个实例来调用,在存在派生类的代码中,知道具体类型还挺麻烦,如果

            类名被修改,那代码就也得改。但 classmethod 方法却可以直接知道类的具体类型,即cls。看一个例子便清楚了:

class Test(object):
    a = 123
    def normalFoo(self):
        print('call normalFoo.')

    @staticmethod
    def staticFoo():
        print('call staticFoo.')
        print(Test.a)
        Test().normalFoo()  # 访问非静态成员

    @classmethod
    def classFoo(cls):
        print('call classFoo.')
        print(Test.a)
        cls().normalFoo()   # 访问非静态成员

Test.staticFoo()
Test.classFoo()

   3)property:把一个方法变成属性调用,起到既能检查属性,还能用属性的方式来访问该属性。

      a. 为什么需要它呢?我们在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把属性随便改:

class Student(object):
    def __init__(self, score = 0):
        self.score = score

s = Student()
s.score = 100
s.score = 200  # 分数为200明显不合理
s.score = -50  # 分数为负数也不合理
print(s.score)

      b. 对值进行约束的一个明显解决方案是隐藏属性score(使其私有)并定义新的 getter 和 setter 接口来操作它。可以按照下面这样改:

class Student(object):
    def __init__(self, value=0):
        self.setScore(value)

    def getScore(self):
        return self._score

    def setScore(self, value):
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

s = Student()
s.setScore(100)
s.setScore(105)     # 报错
s.setScore(-50)     # 报错
print(s.getScore())

       请注意,Python中不存在私有变量,但还是有一些简单的准则可以遵循。Python语言本身并不会做限制。这次更新虽然成功地实现了新的限制,

         但存在的一个大问题是,所有在其程序中实现我们前面的类的客户都必须修改他们的代码,将 s.score 修改为 s.getScore(),并且将像 s.score= val

         的所有赋值语句修改为 s.setScore(val)。这种重构可能会给客户带来数十多万行代码的麻烦。

      c. 这时property就派上用场了。@property真正强大的就是可以对属性增加约束来限制属性的定义。

class Student(object):
    def __init__(self, value=0):
        self._score = value

    @property        # 以需要定义的属性为方法名,如果没有@属性名.setter,则就是一个只读属性
    def score(self):
        return self._score

    @score.setter    # @property定义可访问属性的语法:以属性名为方法名,并在方法名上增加@属性名.setter
    def score(self, value):  
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

s = Student()
s.score = 100    #
s.score = 105    # 报错
s.score = -50    # 报错
print(s.score)

         这样就可以像普通属性那样操作,又可以进行约束。

  

猜你喜欢

转载自www.cnblogs.com/yanghh/p/13208898.html