python中@property注解的具体使用

Written by

in

文章目录
  • @property 是 Python 内置的装饰器,用于将类的方法转换为属性式访问。它允许开发者将方法以属性的形式调用(如 obj.attr 而非 obj.attr()),同时封装属性的读取(getter)、赋值(setter)、删除(deleter)逻辑,实现受控的属性访问(如数据验证、计算属性、隐藏内部变量)。
  • 特性 @property 传统 get_x()/set_x() 调用方式 obj.age(属性式) obj.get_age()(方法式) 封装性 隐藏内部变量(如 _age) 需手动约定命名规范 数据校验 赋值时自动触发 setter 校验 需手动调用 set_x() 校验 代码可读性 更简洁、符合 Python 风格 冗余、不够直观 兼容性 仅新式类支持(Python 3 默认) 全版本兼容
  • 场景 推荐用法 计算属性(如面积、总价) 仅定义 @property(只读) 需要数据校验的属性 定义 @property + @属性名.setter 需要清理资源的属性 额外定义 @属性名.deleter 封装内部变量,对外提供统一访问接口 @property 替代手动 getter/setter 复用属性逻辑(多类共用) 自定义描述符(而非 @property)
  • @property 是 Python 面向对象编程中实现属性封装的核心工具,它以简洁的语法糖封装了描述符协议,兼顾了「易用性」(属性式访问)和「封装性」(受控的读写逻辑)。无论是实现计算属性、数据校验,还是隐藏内部变量,@property 都是比传统 getter/setter 更优雅的选择,是 Python 开发者必须掌握的特性之一。 到此这篇关于python中@property注解的具体使用的文章就介绍到这了,更多相关python @property注解内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: python @property的用法及含义全面解析 介绍Python的@property装饰器的用法 实例讲解Python编程中@property装饰器的用法 python 中的@property的用法详解 Python 中@property的用法详解 Python @property装饰器原理解析 详解Python装饰器之@property Python进阶之@property动态属性的实现 python装饰器中@property属性的使用解析 Python @property原理解析和用法实例 Python如何使用@property @x.setter及@x.deleter Python @property使用方法解析 python中@Property属性使用方法
  • 目录
    • 一、@property核心定义
      • 核心价值:
    • 二、基础用法
      • 1. 只读属性(基础 getter)
      • 2. 可写属性(setter 装饰器)
      • 3. 可删除属性(deleter 装饰器)
    • 三、进阶用法
      • 1. 与继承结合:重写父类的 property
      • 2. 缓存昂贵的计算属性
      • 3. 手动创建 property 对象(非装饰器方式)
    • 四、关键注意事项
      • 1. 命名规范:避免变量名冲突
      • 2. 只读属性的限制
    • 五、@propertyvs 传统 getter/setter
      • 六、适用场景总结
        • 七、总结

          @property 是 Python 内置的装饰器,用于将类的方法转换为属性式访问。它允许开发者将方法以属性的形式调用(如 obj.attr 而非 obj.attr()),同时封装属性的读取(getter)、赋值(setter)、删除(deleter)逻辑,实现受控的属性访问(如数据验证、计算属性、隐藏内部变量)。

          • 替代传统的 get_x()/set_x() 方法,让属性访问更直观、符合 Python 风格;
          • 兼顾封装性(隐藏内部变量)和易用性(属性式调用);
          • 支持动态计算属性(如根据其他属性推导值)、数据校验(如限制属性取值范围)。

          最核心的用法是将方法转为只读属性,适用于「计算属性」(值由其他属性推导,无需手动赋值)。

          示例:圆的面积计算

          class Circle:
              def __init__(self, radius: float):
                  self.radius = radius  # 基础属性
          
              @property
              def area(self) -> float:
                  """计算面积(只读属性),无需调用方法,直接访问"""
                  return 3.1415926 * self.radius **2
          
          # 使用:像访问普通属性一样调用,无需加 ()
          c = Circle(5)
          print(c.area)  # 输出:78.539815
          # 尝试赋值会报错(只读属性)
          # c.area = 100  # AttributeError: can't set attribute
          

          通过 @属性名.setter 装饰器定义赋值逻辑,实现属性的可控写入(如数据验证)。

          示例:年龄属性的校验

          class Person:
              def __init__(self, name: str, age: int):
                  self.name = name
                  self._age = age  # 下划线前缀:约定俗成的「私有变量」(Python 无真正私有)
          
              @property
              def age(self) -> int:
                  """getter:读取年龄"""
                  return self._age
          
              @age.setter
              def age(self, value: int):
                  """setter:赋值时验证数据合法性"""
                  # 类型校验
                  if not isinstance(value, int):
                      raise TypeError("年龄必须是整数")
                  # 范围校验
                  if value < 0 or value > 150:
                      raise ValueError("年龄必须在 0-150 之间")
                  self._age = value
          
          # 使用:赋值时自动触发 setter 校验
          p = Person("Alice", 20)
          print(p.age)  # 20(触发 getter)
          p.age = 25    # 合法赋值(触发 setter)
          # p.age = "30"  # 触发 TypeError
          # p.age = 200   # 触发 ValueError
          

          通过 @属性名.deleter 装饰器定义属性删除逻辑,适用于需要清理资源的场景。

          示例:删除年龄属性

          class Person:
              # (继承上面的 __init__、age getter/setter)
              @age.deleter
              def age(self):
                  """deleter:删除属性时执行的逻辑"""
                  print("删除年龄属性...")
                  del self._age
          
          # 使用:删除属性触发 deleter
          p = Person("Bob", 30)
          del p.age  # 输出:删除年龄属性...
          # 此时访问 p.age 会报错(_age 已被删除)
          # print(p.age)  # AttributeError: 'Person' object has no attribute '_age'
          

          子类可重写父类的 @property 及其 setter/deleter,实现个性化逻辑。

          class Student(Person):
              @property
              def age(self):
                  """重写 getter:添加学生年龄的额外提示"""
                  print(f"学生 {self.name} 的年龄:")
                  return super().age  # 调用父类的 getter
          
              @age.setter
              def age(self, value):
                  """重写 setter:添加学生年龄的特殊校验"""
                  if value < 6 or value > 30:
                      raise ValueError("学生年龄应在 6-30 之间")
                  super(Student, Student).age.fset(self, value)  # 调用父类的 setter
          
          # 测试
          s = Student("Charlie", 18)
          print(s.age)  # 输出:学生 Charlie 的年龄:18
          s.age = 35    # 触发 ValueError
          

          对于计算耗时的属性(如大数据处理、网络请求),可结合 functools.lru_cache 缓存结果,避免重复计算。

          import functools
          
          class DataProcessor:
              def __init__(self, raw_data: list[int]):
                  self.raw_data = raw_data
          
              @property
              @functools.lru_cache(maxsize=None)  # 缓存方法结果
              def processed_data(self) -> list[int]:
                  """模拟昂贵的计算:仅首次调用时计算,后续直接返回缓存"""
                  print("执行昂贵计算...")
                  return [x * 2 + 1 for x in self.raw_data]
          
          # 测试
          dp = DataProcessor([1, 2, 3, 4])
          print(dp.processed_data)  # 输出:执行昂贵计算... [3, 5, 7, 9]
          print(dp.processed_data)  # 直接返回缓存,无打印
          

          @property 本质是语法糖,底层通过 property() 类实现。可手动创建 property 对象,效果与装饰器一致:

          class Person:
              def __init__(self, age: int):
                  self._age = age
          
              # 定义 getter/setter/deleter 方法
              def get_age(self):
                  return self._age
          
              def set_age(self, value):
                  if value < 0:
                      raise ValueError("年龄不能为负")
                  self._age = value
          
              def del_age(self):
                  del self._age
          
              # 手动创建 property 对象:property(fget, fset, fdel, doc)
              age = property(get_age, set_age, del_age, "年龄属性,支持校验")
          
          # 使用方式与装饰器一致
          p = Person(20)
          print(p.age)  # 20
          p.age = 25    # 合法
          

          • 内部存储的变量建议用下划线前缀(如 _age),与 @property 装饰的方法名(如 age)区分,避免无限递归:
            # 错误示例:无限递归
            class Person:
                def __init__(self, age):
                    self.age = age  # 赋值时触发 setter,setter 又赋值 self.age → 递归
            
                @property
                def age(self):
                    return self.age  # 读取时触发 getter,getter 又读取 self.age → 递归
            
            # 正确:内部变量用 _age,property 方法用 age
            

          仅定义 @property(无 setter)的属性是只读的,尝试赋值会抛出 AttributeError,适合纯计算属性。

          特性 @property 传统 get_x()/set_x()
          调用方式 obj.age(属性式) obj.get_age()(方法式)
          封装性 隐藏内部变量(如 _age) 需手动约定命名规范
          数据校验 赋值时自动触发 setter 校验 需手动调用 set_x() 校验
          代码可读性 更简洁、符合 Python 风格 冗余、不够直观
          兼容性 仅新式类支持(Python 3 默认) 全版本兼容

          场景 推荐用法
          计算属性(如面积、总价) 仅定义 @property(只读)
          需要数据校验的属性 定义 @property + @属性名.setter
          需要清理资源的属性 额外定义 @属性名.deleter
          封装内部变量,对外提供统一访问接口 @property 替代手动 getter/setter
          复用属性逻辑(多类共用) 自定义描述符(而非 @property)

          @property 是 Python 面向对象编程中实现属性封装的核心工具,它以简洁的语法糖封装了描述符协议,兼顾了「易用性」(属性式访问)和「封装性」(受控的读写逻辑)。无论是实现计算属性、数据校验,还是隐藏内部变量,@property 都是比传统 getter/setter 更优雅的选择,是 Python 开发者必须掌握的特性之一。

          到此这篇关于python中@property注解的具体使用的文章就介绍到这了,更多相关python @property注解内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

          您可能感兴趣的文章:

          • python @property的用法及含义全面解析
          • 介绍Python的@property装饰器的用法
          • 实例讲解Python编程中@property装饰器的用法
          • python 中的@property的用法详解
          • Python 中@property的用法详解
          • Python @property装饰器原理解析
          • 详解Python装饰器之@property
          • Python进阶之@property动态属性的实现
          • python装饰器中@property属性的使用解析
          • Python @property原理解析和用法实例
          • Python如何使用@property @x.setter及@x.deleter
          • Python @property使用方法解析
          • python中@Property属性使用方法

          站内搜索