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 math

class 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.987
print(c.R * 2)

c.S = 99.88
print(c.S, c.R, end=' ')


11.4                #结果
99.9 5.6

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值