news 2026/6/6 22:12:09

Python property装饰器详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python property装饰器详解

Python@property装饰器详解

@property是 Python 中用于实现属性访问控制的内置装饰器,它可以让你像访问属性一样调用方法。

基本概念

class Person: def __init__(self, name): self._name = name @property def name(self): """获取姓名""" return self._name @name.setter def name(self, value): """设置姓名""" if not isinstance(value, str): raise TypeError("姓名必须是字符串") self._name = value @name.deleter def name(self): """删除姓名""" del self._name # 使用示例 p = Person("张三") print(p.name) # 张三 - 像属性一样访问 p.name = "李四" # 像属性一样赋值 print(p.name) # 李四 del p.name # 像属性一样删除

三种装饰器

1.@property- getter

class Circle: def __init__(self, radius): self._radius = radius @property def radius(self): """获取半径""" return self._radius @property def area(self): """计算面积 - 只读属性""" return 3.14159 * self._radius ** 2 c = Circle(5) print(c.radius) # 5 print(c.area) # 78.53975 # c.area = 100 # 错误!AttributeError: can't set attribute

2.@方法名.setter- setter

class Temperature: def __init__(self, celsius=0): self._celsius = celsius @property def celsius(self): return self._celsius @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("温度不能低于绝对零度") self._celsius = value @property def fahrenheit(self): """只读属性""" return self._celsius * 9/5 + 32 t = Temperature(25) t.celsius = 30 # 使用setter print(t.celsius) # 30 # t.celsius = -300 # ValueError!

3.@方法名.deleter- deleter

class User: def __init__(self, username): self._username = username self._password = "secret" @property def password(self): return self._password @password.deleter def password(self): """删除密码""" print("正在删除密码...") del self._password user = User("alice") print(user.password) # secret del user.password # 正在删除密码... # print(user.password) # AttributeError

实际应用场景

1. 数据验证

class Student: def __init__(self, name, age, score): self.name = name self.age = age self.score = score @property def name(self): return self._name @name.setter def name(self, value): if not value or not value.strip(): raise ValueError("姓名不能为空") self._name = value.strip() @property def age(self): return self._age @age.setter def age(self, value): if not isinstance(value, int): raise TypeError("年龄必须是整数") if value < 0 or value > 150: raise ValueError("年龄必须在0-150之间") self._age = value @property def score(self): return self._score @score.setter def score(self, value): if not 0 <= value <= 100: raise ValueError("分数必须在0-100之间") self._score = value @property def grade(self): """只读属性 - 根据分数计算等级""" if self._score >= 90: return "A" elif self._score >= 80: return "B" elif self._score >= 70: return "C" elif self._score >= 60: return "D" else: return "F" s = Student("张三", 18, 85) print(f"{s.name}, {s.age}岁, 成绩{s.score}, 等级{s.grade}")

2. 延迟计算/缓存

class DataProcessor: def __init__(self, data): self.data = data self._processed = None @property def processed_data(self): """延迟计算,结果会被缓存""" if self._processed is None: print("正在处理数据...") self._processed = [x * 2 for x in self.data] return self._processed dp = DataProcessor([1, 2, 3, 4, 5]) print(dp.processed_data) # 第一次:正在处理数据... [2,4,6,8,10] print(dp.processed_data) # 第二次:直接返回 [2,4,6,8,10](不打印)

3. 属性依赖更新

class Rectangle: def __init__(self, width, height): self._width = width self._height = height self._area = None @property def width(self): return self._width @width.setter def width(self, value): self._width = value self._area = None # 清除缓存 @property def height(self): return self._height @height.setter def height(self, value): self._height = value self._area = None @property def area(self): if self._area is None: self._area = self._width * self._height return self._area r = Rectangle(5, 3) print(r.area) # 15(计算) r.width = 10 print(r.area) # 30(重新计算)

使用@property的优点

1. 向后兼容

# 最初版本 - 直接使用属性 class PersonV1: def __init__(self, name): self.name = name # 后续版本 - 需要添加验证,但不影响现有代码 class PersonV2: def __init__(self, name): self._name = name @property def name(self): return self._name @name.setter def name(self, value): if not value: raise ValueError("Name cannot be empty") self._name = value # 现有代码 p.name = "张三" 仍然可以正常工作

2. 封装逻辑

class BankAccount: def __init__(self, balance=0): self._balance = balance self._transactions = [] @property def balance(self): """只读属性""" return self._balance def deposit(self, amount): if amount <= 0: raise ValueError("存款金额必须为正数") self._balance += amount self._transactions.append(f"存款: +{amount}") def withdraw(self, amount): if amount <= 0: raise ValueError("取款金额必须为正数") if amount > self._balance: raise ValueError("余额不足") self._balance -= amount self._transactions.append(f"取款: -{amount}") @property def transaction_history(self): """只读属性""" return self._transactions.copy() acc = BankAccount(1000) acc.deposit(500) acc.withdraw(200) print(f"余额: {acc.balance}") # 1300 print(f"交易记录: {acc.transaction_history}") # acc.balance = 9999 # 错误!无法直接修改

注意事项

  1. 命名约定:通常使用下划线前缀(_)表示私有属性

  2. 性能考虑@property方法会有轻微的性能开销

  3. 不要滥用:简单的属性访问不需要使用@property

  4. 继承行为@property会被子类继承

class Parent: @property def value(self): return 10 class Child(Parent): @property def value(self): return 20 # 可以覆盖 c = Child() print(c.value) # 20

总结

@property是 Python 中实现封装和数据验证的优雅方式,它让你能够:

  • 在访问属性时添加逻辑(验证、计算等)

  • 创建只读属性

  • 实现延迟计算

  • 保持向后兼容性

  • 提供清晰的 API 设计

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 22:08:24

如何高效使用网盘直链下载助手:免费获取真实下载链接的完整方案

如何高效使用网盘直链下载助手&#xff1a;免费获取真实下载链接的完整方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云…

作者头像 李华
网站建设 2026/6/6 22:07:18

MAA助手完整指南:明日方舟终极自动化管理工具

MAA助手完整指南&#xff1a;明日方舟终极自动化管理工具 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手&#xff0c;全日常一键长草&#xff01;| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https://gitcode.com…

作者头像 李华
网站建设 2026/6/6 22:06:21

微创实习日记(一)

已经入职有有一段时间了&#xff0c;现对目前的工作进行一下梳理与总结。一、软件下载与环境搭建软件环境&#xff1a;TwinCAT 3 4024.66 Visual Studio2019工作任务&#xff1a;根据手册下载安装TwinCAT3 4024.66与VS2019&#xff0c;并通过新建PLC程序、C程序验证开发环境正…

作者头像 李华
网站建设 2026/6/6 22:04:57

8、网络层

网络层在复杂的网络环境中确定一个合适的路径.IP协议基本概念主机: 配有 IP 地址, 但是不进行路由控制的设备;路由器: 即配有 IP 地址, 又能进行路由控制;节点: 主机和路由器的统称;协议头格式• 4 位版本号(version): 指定 IP 协议的版本, 对于 IPv4 来说, 就是 4.• 4 位头部…

作者头像 李华