python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > python @property注解

python中@property注解的具体使用

作者:大、男人

property是 Python 内置的装饰器,用于将类的方法转换为属性式访问,本文就来详细的介绍一下@property注解的使用,感兴趣的可以了解一下

一、@property核心定义

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

核心价值:

二、基础用法

1. 只读属性(基础 getter)

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

示例:圆的面积计算

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

2. 可写属性(setter 装饰器)

通过 @属性名.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

3. 可删除属性(deleter 装饰器)

通过 @属性名.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'

三、进阶用法

1. 与继承结合:重写父类的 property

子类可重写父类的 @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

2. 缓存昂贵的计算属性

对于计算耗时的属性(如大数据处理、网络请求),可结合 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)  # 直接返回缓存,无打印

3. 手动创建 property 对象(非装饰器方式)

@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    # 合法

四、关键注意事项

1. 命名规范:避免变量名冲突

2. 只读属性的限制

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

五、@propertyvs 传统 getter/setter

特性@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注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文