亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> Python

精通 Python @property 装饰器:简洁、向后兼容的 Getter 与 Setter

精通 Python @property 装饰器

了解 Python 内置 @property 装饰器如何让你编写简洁、可维护的 getter 和 setter,同时保持 API 向后兼容。

Python 的 @property 装饰器是封装属性访问的强大工具。它让你定义属性读写时运行的自定义逻辑,而无需强制调用者修改代码。以下章节将通过真实案例——处理温度转换——演示如何强制约束,并解释为何 @property 是地道解决方案。


无 Getter/Setter 的类

假设需要一个简单类存储摄氏温度并能转华氏度:

class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

使用很简单:

# 创建新对象
human = Celsius()
# 设置温度
human.temperature = 37
# 读取温度
print(human.temperature)
# 转华氏度
print(human.to_fahrenheit())

输出

37 98.60000000000001

浮点结果因十进制二进制表示预期。查看 human.__dict__ 可见 Python 在普通字典条目存储值:

>>> human.__dict__
{'temperature': 37}

用 Getter/Setter 添加约束

真实对象常需验证。如温度不能低于绝对零度(-273.15 °C)。直接方式是隐藏属性并暴露显式 getter/setter:

class Celsius:
    def __init__(self, temperature=0):
        self.set_temperature(temperature)
    def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32
    # getter
    def get_temperature(self):
        return self._temperature
    # setter
    def set_temperature(self, value):
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible.")
        self._temperature = value

类虽强制下界,但现有代码访问 obj.temperature 必须改为 obj.get_temperature() 和 obj.set_temperature(val)。大型代码库这意味着大规模重构。

且 Python “私有”变量仅是命名约定——_temperature 仍可直接访问,破坏封装。@property 正是解决此问题。


使用 property 类

Python 提供 property 类将 getter/setter 函数绑定到属性名:

class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
    # getter
    def get_temperature(self):
        print("Getting value...")
        return self._temperature
    # setter
    def set_temperature(self, value):
        print("Setting value...")
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible")
        self._temperature = value
    # 暴露为 property
    temperature = property(get_temperature, set_temperature)

此设置下,以下代码行为与原简单类完全一致,但背后有验证:

human = Celsius(37)
print(human.temperature)  # 触发 getter
print(human.to_fahrenheit())  # 内部用 getter
human.temperature = -300  # 触发 setter 并引发 ValueError

输出

Setting value... Getting value... 37 Getting value... 98.60000000000001 Setting value... Traceback (most recent call last): ... ValueError: Temperature below -273 is not possible

注意访问 temperature 的代码未变;仅底层实现获得验证。

提示:实际数据存在 _temperature;temperature 只是方便安全的接口。


@property 装饰器

property 类虽可用,但 Python 装饰器语法提供更清晰、可读的方式达成同等效果。装饰器自动创建 property 对象并将 getter/setter 绑定到属性名。

class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
    @property
    def temperature(self):
        print("Getting value...")
        return self._temperature
    @temperature.setter
    def temperature(self, value):
        print("Setting value...")
        if value < -273.15:
            raise ValueError("Temperature below -273 is not possible")
        self._temperature = value

用法保持不变:

human = Celsius(37)
print(human.temperature)
print(human.to_fahrenheit())
# 尝试设置无效温度
try:
    Celsius(-300)
except ValueError as e:
    print(e)

输出

Setting value... Getting value... 37 Getting value... 98.60000000000001 Setting value... Traceback (most recent call last): ... ValueError: Temperature below -273 is not possible

使用 @property 保持命名空间整洁,免去单独 getter/setter 方法名,是大多数 Python 开发者的推荐模式。

Python

  1. 精通Python数据类型:实战指南
  2. 精通Python运算符:全面指南
  3. 精通Python Pass语句:实战指南
  4. 精通Python函数参数:位置、关键字与默认参数
  5. 精通 Python 字典:创建、操作与进阶技巧
  6. 精通 Python 继承:概念、语法与实战示例
  7. 精通 Python 运算符重载:实战指南
  8. 精通 Python 迭代器:工作原理与自定义构建
  9. Python 闭包详解:嵌套函数如何捕获变量
  10. 精通 Python @property 装饰器:简洁、向后兼容的 Getter 与 Setter
  11. 精通 Python datetime:日期、时间与时区实战指南
  12. 精通 Python time.sleep():最佳实践、多线程与实战案例