python属性修饰器

在 Python 中,属性装饰器(@property 是一种用于管理类属性访问的高级工具,它可以让你在访问或修改属性时添加自定义逻辑(如数据验证、计算属性等)。


1. 基础用法:将方法伪装成属性

@property 允许你通过属性语法(.)调用方法,无需显式加括号。

示例:定义一个温度类

class Celsius:
    def __init__(self, temperature=0):
        self._temperature = temperature  # 内部使用私有变量

    @property
    def temperature(self):
        print("Getting temperature...")
        return self._temperature

    @temperature.setter
    def temperature(self, value):
        print("Setting temperature...")
        if value < -273.15:
            raise ValueError("Temperature below absolute zero is impossible")
        self._temperature = value

# 使用示例
c = Celsius(25)
print(c.temperature)  # 输出: Getting temperature... 25
c.temperature = 30    # 输出: Setting temperature...
# c.temperature = -300  # 抛出 ValueError
  • @property:定义 temperature获取方法(getter)
  • @temperature.setter:定义 temperature设置方法(setter)
  • @temperature.deleter(可选):定义删除属性的逻辑。

2. 只读属性

如果只定义 @property 而不定义 setter,则属性为只读。

示例:计算圆的面积

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

    @property
    def area(self):
        return 3.14159 * self.radius ** 2

# 使用示例
circle = Circle(5)
print(circle.area)  # 输出: 78.53975
# circle.area = 100  # 报错:AttributeError(没有 setter)

3. 数据验证与保护

通过 setter 方法,可以在赋值时添加逻辑(如范围检查)。

示例:年龄验证

class Person:
    def __init__(self, name):
        self.name = name
        self._age = 0  # 内部私有变量

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not 0 <= value <= 120:
            raise ValueError("Age must be between 0 and 120")
        self._age = value

# 使用示例
p = Person("Alice")
p.age = 30
print(p.age)  # 输出: 30
# p.age = 150  # 抛出 ValueError

4. 动态计算属性

属性值可以动态计算,而非固定存储。

示例:矩形的面积和周长

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

    @property
    def area(self):
        return self.width * self.height

    @property
    def perimeter(self):
        return 2 * (self.width + self.height)

# 使用示例
rect = Rectangle(4, 5)
print(rect.area)      # 输出: 20
print(rect.perimeter) # 输出: 18

5. 属性删除逻辑

通过 @property.deleter 定义删除属性时的行为。

示例:删除敏感数据

class User:
    def __init__(self, username, password):
        self.username = username
        self._password = password

    @property
    def password(self):
        return "******"  # 隐藏真实密码

    @password.deleter
    def password(self):
        print("Password is being deleted...")
        del self._password

# 使用示例
user = User("admin", "secret123")
print(user.password)  # 输出: ******
del user.password     # 输出: Password is being deleted...

6. 替代传统 Getter/Setter

使用 @property 可以避免手动编写 get_xxx()set_xxx() 方法,使代码更简洁。

传统写法 vs 属性装饰器

# 传统写法(冗余)
class OldStyle:
    def __init__(self):
        self._value = 0

    def get_value(self):
        return self._value

    def set_value(self, value):
        if value < 0:
            raise ValueError("Value must be positive")
        self._value = value

# 属性装饰器(简洁)
class NewStyle:
    def __init__(self):
        self._value = 0

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        if value < 0:
            raise ValueError("Value must be positive")
        self._value = value

7. 最佳实践

  1. 优先使用 @property:替代手动编写 getter/setter
  2. 避免复杂逻辑:保持 @property 方法简单,避免耗时操作。
  3. 命名规范:私有变量用下划线前缀(如 _value),属性方法用公开名称。
  4. 只读属性:如果不希望属性被修改,不要定义 setter

实战项目

  1. 项目 1:实现一个银行账户类,使用 @property 确保余额不为负。
  2. 项目 2:创建一个学生类,动态计算平均成绩(通过 @property)。
  3. 项目 3:用 @property 验证用户输入的邮箱格式。

我曾走过山,走过水,其实只是借助它们走过我的生命。 —史铁生

你可能感兴趣的:(python,开发语言)