Python property 函数
上次修改时间:2025 年 4 月 11 日
本综合指南探讨了 Python 的 property 函数,该函数创建具有 getter、setter 和 deleter 方法的托管属性。我们将介绍基本用法、装饰器语法和实际示例。
基本定义
property 函数返回一个 property 属性。它提供了一种使用方法封装实例属性访问的方式。这使得数据验证、计算属性和只读属性成为可能。
主要特点:接受可选的 getter、setter、deleter 和文档字符串参数。返回一个 property 对象,该对象在访问时使用这些方法。它是 Python 中的内置描述符类型。
基本 Property 用法
这是一个简单的用法示例,展示了如何为温度类创建一个带有验证的 property。该 property 确保温度保持在绝对零度以上。
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
def get_celsius(self):
return self._celsius
def set_celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below absolute zero")
self._celsius = value
celsius = property(get_celsius, set_celsius)
temp = Temperature(25)
print(temp.celsius) # 25
temp.celsius = 30
print(temp.celsius) # 30
try:
temp.celsius = -300 # Raises ValueError
except ValueError as e:
print(e)
此示例演示了如何使用单独的 getter 和 setter 方法创建 property。该 property 确保温度值在物理上有效,同时保持一个干净的接口。
_celsius 命名约定表明它是一个受保护的属性。用户与 celsius property 交互,而不是与属性交互。
Property 装饰器语法
Python 的装饰器语法提供了一种更简洁的方式来定义 property。此示例演示了使用装饰器的相同温度类。
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below absolute zero")
self._celsius = value
temp = Temperature(25)
print(temp.celsius) # 25
temp.celsius = -100
print(temp.celsius) # -100
装饰器语法更具可读性,并将相关方法组合在一起。@property 装饰器创建 getter,而 @celsius.setter 创建 setter。
这种方法在现代 Python 代码中更受欢迎,因为它清楚地表明了哪些方法属于该 property。
只读 Property
Property 可以通过省略 setter 来创建只读属性。此示例显示了一个具有计算的只读面积 property 的圆形类。
import math
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * self.radius ** 2
circle = Circle(5)
print(circle.area) # 78.53981633974483
try:
circle.area = 100 # Raises AttributeError
except AttributeError as e:
print("Can't set area:", e)
area property 从半径计算得出,不能直接设置。尝试设置它会引发 AttributeError。
此模式对于仅当其源属性更改时才应更改的派生属性很有用。
带有 Deleter 的 Property
Property 还可以定义 deleters 以进行清理操作。此示例显示了一个具有基于 property 的资源管理的文件处理程序类。
class FileHandler:
def __init__(self, filename):
self._filename = filename
self._file = open(filename, 'r')
@property
def file(self):
return self._file
@file.deleter
def file(self):
if self._file:
self._file.close()
self._file = None
handler = FileHandler('example.txt')
print(handler.file.read(10))
del handler.file # Closes the file
deleter 确保在删除 property 时进行适当的资源清理。这比依赖 __del__ 或上下文管理器更明确。
该 property 提供了对文件对象的受控访问,同时保持了在需要时正确关闭它的能力。
动态 Property
Property 可以从其他属性动态计算值。此示例显示了一个具有动态宽度/高度 property 的矩形类。
class Rectangle:
def __init__(self, x1, y1, x2, y2):
self.x1, self.y1 = x1, y1
self.x2, self.y2 = x2, y2
@property
def width(self):
return abs(self.x2 - self.x1)
@width.setter
def width(self, value):
if value <= 0:
raise ValueError("Width must be positive")
self.x2 = self.x1 + value
@property
def height(self):
return abs(self.y2 - self.y1)
@height.setter
def height(self, value):
if value <= 0:
raise ValueError("Height must be positive")
self.y2 = self.y1 + value
rect = Rectangle(0, 0, 10, 20)
print(rect.width, rect.height) # 10 20
rect.width = 15
print(rect.width) # 15
宽度和高度 property 是从坐标计算得出的,但也可以设置,这将更新坐标。这保持了数据一致性。
当您想要呈现相同底层数据的不同视图,同时保持一切同步时,此方法非常有用。
最佳实践
- 用于封装: 将实现细节隐藏在 property 之后
- 首选装饰器语法: 为了更简洁、更具可读性的代码
- 文档 property: 包括解释行为的文档字符串
- 在 setter 中验证: 确保数据保持一致
- 考虑性能: 计算的 property 可能会影响性能
资料来源
作者
列出所有 Python 教程。