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

Myth丶恋晨 2023-06-29 10:37 37阅读 0赞

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

  1. circle.get_radius() #调用方法
  2. circle.set_radius(5.0) #繁
  3. circle.radius #访问属性
  4. circle.redius = 5.0 #简

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

解决方案:

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


  • 对于property()函数:

    property(fget=None, fset=None, fdel=None, doc=None)

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

  1. class C:
  2. def __init__(self):
  3. self._x = None
  4. def getx(self):
  5. return self._x
  6. def setx(self, value):
  7. self._x = value
  8. def delx(self):
  9. del self._x
  10. 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:

    1. def __init__(self, radius):
    2. self.radius = radius
    3. def get_radius(self):
    4. return round(self.radius, 1)
    5. def set_radius(self, radius):
    6. if not isinstance(radius, (int, float)):
    7. raise TypeError('wrong type')
    8. self.redius = radius
    9. @property
    10. # def get_area(self):
    11. def S(self):
    12. return round(self.radius ** 2 * math.pi, 1)
    13. @S.setter
    14. # def set_area(self, s):
    15. def S(self, s):
    16. self.radius = math.sqrt(s / math.pi)
    17. 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=’ ‘)

  1. 11.4 #结果
  2. 99.9 5.6

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


发表评论

表情:
评论列表 (有 0 条评论,37人围观)

还没有评论,来说两句吧...

相关阅读

    相关 33. 创建管理对象属性

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