zoukankan      html  css  js  c++  java
  • python基础===装饰器@property 的扩展

    以下来自Python 3.6.0 Document:
    class property(fget=None, fset=None, fdel=None, doc=None)

    Return a property attribute.

    fget is a function for getting an attribute value. fset is a function for setting an attribute value. fdel is a function for deleting an attribute value. And doc creates a docstring for the attribute.

    A typical use is to define a managed attribute x:

    class C:
        def __init__(self):
            self._x = None
    
        def getx(self):
            return self._x
    
        def setx(self, value):
            self._x = value
    
        def delx(self):
            del self._x
    
        x = property(getx, setx, delx, "I'm the 'x' property.")

    If c is an instance of C, c.x will invoke the getter, c.x = value will invoke the setter and del c.x the deleter.

    If given, doc will be the docstring of the property attribute. Otherwise, the property will copy fget‘s docstring (if it exists). This makes it possible to create read-only properties easily using property() as a decorator:

    class Parrot:
        def __init__(self):
            self._voltage = 100000
    
        @property
        def voltage(self):
            """Get the current voltage."""
            return self._voltage

    The @property decorator turns the voltage() method into a “getter” for a read-only attribute with the same name, and it sets the docstring for voltage to “Get the current voltage.”

    A property object has getter, setter, and deleter methods usable as decorators that create a copy of the property with the corresponding accessor function set to the decorated function. This is best explained with an example:

    class C:
        def __init__(self):
            self._x = None
    
        @property
        def x(self):
            """I'm the 'x' property."""
            return self._x
    
        @x.setter
        def x(self, value):
            self._x = value
    
        @x.deleter
        def x(self):
            del self._x

    This code is exactly equivalent to the first example. Be sure to give the additional functions the same name as the original property (x in this case.)

    The returned property object also has the attributes fget, fset, and fdel corresponding to the constructor arguments.

    Changed in version 3.5: The docstrings of property objects are now writeable.

    先看一段代码:

     

    class stu:
        def __init__(self,name):
            self.name = name
    
        def get_score(self):
            return self.score
    
        def set_score(self, score):
            if not isinstance(score, int):
                raise ValueError("score must be an integer~")
            if score>100 or score<0:
                raise ValueError("score must between 0~100")
            self.score = score
    
    s = stu("Botoo")
    #s.set_score(100)            #score must be an integer~
    #s.set_score("dasda")    #score must between 0~100
    s.set_score(98)
    print(s.get_score())        #98

     

    这种使用 get/set 方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。

    但是写 s.get_score() 和 s.set_score() 没有直接写 s.score 来得直接。

    因为Python支持高阶函数,可以用装饰器函数把 get/set 方法“装饰”成属性调用:

     

    再比较:

    class Student:
        def __init__(self,name):
            self.name = name
    
        @property
        def score(self):
            return self._score
    
        @score.setter
        def score(self,value):
            if not isinstance(value, int):
                raise ValueError('分数必须是整数才行呐')
            if value < 0 or value > 100:
                raise ValueError('分数必须0-100之间')
            self._score = value
            
    S1 = Student("botoo")
    S1.score = 50
    
    print(S1.score)         #50
    S1.score = 500         #ValueError: 分数必须0-100之间

     

    第一个score(self)是get方法,用@property装饰,第二个score(self, score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。

    在子类中扩展一个property可能会引起很多不易察觉的问题, 因为一个property其实是 gettersetterdeleter 方法的集合,而不是单个方法。 因此,当你扩展一个property的时候,你需要先确定你是否要重新定义所有的方法还是说只修改其中某一个。

    • 只有@property表示只读。
    • 同时有@property和@x.setter表示可读可写。
    • 同时有@property和@x.setter和@x.deleter表示可读可写可删除。

    参考:

    http://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p08_extending_property_in_subclass.html

    https://blog.csdn.net/u013205877/article/details/77804137

    https://blog.csdn.net/sxingming/article/details/52916249

  • 相关阅读:
    【bzoj2006】超级钢琴
    【bzoj4940】这是我自己的发明
    【arc076E】Connected?
    【agc004C】AND Grid
    选举
    几何
    打击目标
    【CF Gym100228】Graph of Inversions
    【CodeChef】Chef and Graph Queries
    大包子玩游戏
  • 原文地址:https://www.cnblogs.com/botoo/p/8883944.html
Copyright © 2011-2022 走看看