33. 创建可管理的对象属性

在面向对象编程中,我们把方法(函数)看作对象的接口。直接访问对象的属性可能是不安全的,或导致设计上不够灵活,但是使用调用方法在形式上不如访问属性简洁。例如:

circle.get_radius()             #调用方法
circle.set_radius(5.0)              #繁

circle.radius               #访问属性
circle.redius = 5.0             #简

要求:实现在形式上是访问属性,实际上内部调用方法。

解决方案:

使用内置的property()函数为类创建可管理属性,fget/fset/fdel对象属性访问/设置/删除。


  • 对于property()函数:
property(fget=None, fset=None, fdel=None, doc=None)

返回property属性。fget是获取属性值的函数。fset是用于设置属性值的函数。fdel是用于删除属性值的函数。并且doc为属性对象创建文档字符串。

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.")

如果c是C的实例,c.x将调用getter方法获取属性,c.x = value将调用setter方法设置属性,del c.x将调用deleter方法删除属性。

如果给出doc,doc将成为该property属性的文档字符串,否则该property将拷贝fget的文档字符串(如果存在)。

此外,如果property()函数只定义fget(getter),则定义的属性为只读属性。


  • 方案示例:
import mathclass Circle:
    def __init__(self, radius):
        self.radius = radius    
    def get_radius(self):
        return round(self.radius, 1)

    def set_radius(self, radius):
        if not isinstance(radius, (int, float)):
            raise TypeError('wrong type')
        self.redius = radius

    @property
    # def get_area(self):
    def S(self):
        return round(self.radius ** 2 * math.pi, 1)
    
    @S.setter    # def set_area(self, s):
    def S(self, s):
        self.radius = math.sqrt(s / math.pi)

    R = property(get_radius, set_radius)c = Circle(5.712)c.R = 100.987print(c.R * 2)c.S = 99.88print(c.S, c.R, end=' ')11.4                #结果99.9 5.6

通过property()函数定义属性R,来调用get_radius()set_radius()方法。通过@property装饰器装饰S,达到与定义R属性一样的效果。


上一篇:Oracel期末复习知识点——背完这33题想挂都难


下一篇:springboot--33--Swagger配置扫描接口及开关