在面向对象编程中,我们常常需要对类的属性访问进行控制。例如,某些属性需要在获取时自动计算,或在设置时进行验证。Python 提供了内置函数 property(),它能将类的方法转换为“属性访问”的形式,从而实现更优雅的封装。

一、函数语法

property(fget=None, fset=None, fdel=None, doc=None)

参数:

fget:可选。获取属性值的函数(对应 getter)。

fset:可选。设置属性值的函数(对应 setter)。

fdel:可选。删除属性值的函数(对应 deleter)。

doc:可选。属性的文档字符串。

返回值:

返回一个 property 对象,可以作为类的属性使用。

二、基础用法示例

1、使用 property() 创建只读属性

class Circle:
    def __init__(self, radius):
        self._radius = radius

    def get_area(self):
        return 3.14 * self._radius ** 2

    area = property(get_area)    # area 就是通过 property() 创建的只读属性

c = Circle(5)
print(c.area)  # 78.5
# c.area = 100  # AttributeError: can't set attribute

2、定义 getter、setter、deleter

class Person:
    def __init__(self, name):
        self._name = name

    def get_name(self):
        return self._name

    def set_name(self, value):
        if not isinstance(value, str):
            raise ValueError("名字必须是字符串")
        self._name = value

    def del_name(self):
        print("删除名字属性")
        del self._name

    name = property(get_name, set_name, del_name, "姓名属性")

p = Person("Alice")
print(p.name)     # 读取 → 调用 get_name
p.name = "Bob"    # 写入 → 调用 set_name
del p.name        # 删除 → 调用 del_name

三、进阶技巧

1、使用装饰器语法

在现代 Python 中,通常用 @property 装饰器及其配套的 @ .setter、@ .deleter 来代替直接调用 property()。

class Rectangle:
    def __init__(self, width, height):
        self._width = width
        self._height = height

    @property
    def area(self):
        return self._width * self._height

    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, value):
        if value <= 0:
            raise ValueError("宽度必须为正数")
        self._width = value

r = Rectangle(3, 4)
print(r.area)   # 12
r.width = 10
print(r.area)   # 40

2、控制属性访问逻辑

property() 常用于:

(1)数据验证(setter 中做检查)。

(2)只读属性(只定义 getter)。

(3)懒加载计算(在 getter 中动态生成)。

(4)封装内部实现(外部访问时仍像普通属性)。

四、property() 特点

property 对象本质上是一个数据描述符,通过 __get__、__set__、__delete__ 方法实现属性访问控制。

1、优点

统一了“方法调用”和“属性访问”的接口形式,提高代码可读性。

保持对外接口不变的情况下,可以随时在内部增加逻辑。

2、兼容性

property() 与 @property 装饰器写法等价。

推荐装饰器写法,更简洁、直观。

五、补充说明

1、property 与封装

它体现了面向对象中的封装思想,把属性保护在内部,仅通过受控接口访问。

2、常见误区

误以为 property 是语法糖;实际上它是一个类(class property),实现了描述符协议。

3、property 只在类定义中使用;在实例中直接调用 property() 不会生效。

4、应用场景

数据模型(ORM 框架)。

配置类(对外接口稳定,内部逻辑可扩展)。

动态计算属性(如面积、体积、缓存属性)。

小结

property() 是 Python 提供的属性访问控制机制,它将方法转换为属性访问,既能隐藏实现细节,又能增加数据校验和逻辑处理。无论是通过 property() 函数还是 @property 装饰器,合理使用它都能让代码更优雅、更安全。

点赞有美意,赞赏是鼓励