属性(properties)

Tip

访问和设置数据成员时, 你通常会使用简单, 轻量级的访问和设置函数. 建议用属性(properties)来代替它们.

定义:
一种用于包装方法调用的方式. 当运算量不大, 它是获取和设置属性(attribute)的标准方式.
优点:
通过消除简单的属性(attribute)访问时显式的get和set方法调用, 可读性提高了. 允许懒惰的计算. 用Pythonic的方式来维护类的接口. 就性能而言, 当直接访问变量是合理的, 添加访问方法就显得琐碎而无意义. 使用属性(properties)可以绕过这个问题. 将来也可以在不破坏接口的情况下将访问方法加上.
缺点:
属性(properties)是在get和set方法声明后指定, 这需要使用者在接下来的代码中注意: set和get是用于属性(properties)的(除了用 @property 装饰器创建的只读属性). 必须继承自object类. 可能隐藏比如操作符重载之类的副作用. 继承时可能会让人困惑.
结论:

你通常习惯于使用访问或设置方法来访问或设置数据, 它们简单而轻量. 不过我们建议你在新的代码中使用属性. 只读属性应该用 @property 装饰器 来创建.

如果子类没有覆盖属性, 那么属性的继承可能看上去不明显. 因此使用者必须确保访问方法间接被调用, 以保证子类中的重载方法被属性调用(使用模板方法设计模式).




  1. Yes: import math

    class Square(object):
    """A square with two properties: a writable area and a read-only perimeter.

    To use:
    >>> sq = Square(3)
    >>> sq.area
    9
    >>> sq.perimeter
    12
    >>> sq.area = 16
    >>> sq.side
    4
    >>> sq.perimeter
    16
    """

    def init(self, side):
    self.side = side

    def getarea(self):
    """Calculates the 'area' property."""
    return self.side ** 2

    def
    get_area(self):
    """Indirect accessor for 'area' property."""
    return self.get_area()

    def
    set_area(self, area):
    """Sets the 'area' property."""
    self.side = math.sqrt(area)

    def set_area(self, area):
    """Indirect setter for 'area' property."""
    self._SetArea(area)

    area = property(
    get_area, ___set_area,
    doc="""Gets or sets the area of the square.""")

    @property
    def perimeter(self):
    return self.side * 4




(译者注: 老实说, 我觉得这段示例代码很不恰当, 有必要这么蛋疼吗?)