Python3:@property属性装饰器

@property 是 Python 中用来装饰方法的一个内置装饰器。它的主要作用是将一个方法转化为一个属性,使得该方法可以像属性一样被访问,而不需要使用函数调用的方式。这样做的好处是可以在不改变代码结构的情况下,将方法访问转变为属性访问,从而提高代码的可读性和易用性。

属性介绍:

函数方法我们应该并不陌生,属性其实也一样,只是我们很少口语化提这个说法。在 Python 中,属性是与对象相关联的特性或数据。属性可以是对象的状态信息,也可以是对象的行为。具体来说,属性可以分为两种类型:

  • 实例属性(Instance Attributes):实例属性是与特定对象实例相关联的属性。每个对象实例都可以有自己独立的实例属性,它们保存在对象的命名空间中。实例属性通常在对象的构造函数 __init__ 中初始化,也可以在任何地方动态添加或修改。例如:
class Person:
    def __init__(self, name, age):
        self.name = name  # 实例属性
        self.age = age    # 实例属性

person1 = Person("Alice", 30)
person2 = Person("Bob", 25)

print(person1.name)  # 输出:Alice
print(person2.age)   # 输出:25
  • 类属性(Class Attributes):类属性是与类本身相关联的属性,它们被所有该类的对象实例所共享。类属性通常在类的定义体中直接声明,也可以通过类名访问和修改。例如:
class Circle:
    pi = 3.14  # 类属性

    def __init__(self, radius):
        self.radius = radius  # 实例属性

circle1 = Circle(5)
circle2 = Circle(10)

print(circle1.pi)     # 输出:3.14
print(circle2.radius) # 输出:10

# 修改类属性
Circle.pi = 3.14159
print(circle1.pi)     # 输出:3.14159
print(circle2.pi)     # 输出:3.14159

总的来说,属性是对象的特性,可以包含对象的状态信息或行为。实例属性是与特定对象实例相关联的属性,而类属性是与整个类相关联的属性。在 Python 中,属性可以是任何数据类型,包括数字、字符串、列表、元组、字典等。

那么除了类,还有其它属性的示例吗?

除了类属性和实例属性,还有一些其他类型的属性,例如模块属性和函数属性。

  • 模块属性(Module Attributes):模块属性是与 Python 模块相关联的属性,它们存储在模块的命名空间中,并且可以在模块中的任何地方访问。模块属性通常在模块的顶层定义,可以通过导入模块的方式来访问和使用。
# module.py
PI = 3.14
name = "module"

def greet():
    print("Hello from module")

# main.py
import module

print(module.PI)   # 输出:3.14
print(module.name) # 输出:"module"
module.greet()     # 输出:Hello from module
  • 函数属性(Function Attributes):函数属性是与 Python 函数相关联的属性,它们存储在函数的命名空间中,并且可以在函数内部或外部访问。函数属性通常用于存储函数的元数据或配置信息。
def greet(name):
    print("Hello, " + name)

greet.version = 1.0
greet.author = "John Doe"

print(greet.version)  # 输出:1.0
print(greet.author)   # 输出:"John Doe"

这些示例展示了不同类型的属性在 Python 中的使用方式。模块属性用于存储模块级别的信息,而函数属性用于存储函数级别的信息。在 Python 中,属性是一种非常灵活和强大的特性,可以用于各种目的,包括数据存储、元数据存储、配置管理等。

@property示例:

举个例子,假设有一个类 Person,其中有一个方法 get_age() 用来获取年龄,使用 @property 装饰器可以将这个方法转化为一个属性 age文件名:person.py。

class Person:
    def __init__(self, age):
        self._age = age

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

    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("Age cannot be negative")
        self._age = value


# 创建对象
person = Person(10)
print(person.age)

# 修改属性值
person.age = 20
print(person.age)

运行结果:

$ python3 temp.py 
10
20

这样,当我们创建 Person 对象时,可以直接通过 person.age 来访问年龄,而无需使用 person.get_age() 这样的方法调用。同时,如果我们需要在设置年龄时进行一些额外的逻辑,比如确保年龄不为负数,可以通过 @age.setter 装饰器定义一个 setter 方法来实现。

@property的优点:

当你使用 @property 装饰器时,你在某种程度上定义了一种“虚拟属性”。这个属性的值并不是简单地从实例变量中获取,而是通过一个方法来计算或获取。这种方式提供了一些优势:

  1. 简化代码:通过使用 @property,你可以在不改变外部代码的情况下,将方法调用转化为属性访问。这使得代码更加简洁和易读。

  2. 隐藏复杂性:有时,属性的值可能并非简单地存储在实例变量中,而是需要经过复杂的计算或处理才能得到。通过 @property,你可以将这些复杂性隐藏在方法内部,使外部代码更加简单。

  3. 保持接口一致性:使用 @property 可以使得类的接口更加一致。无论是获取属性值还是执行某种操作,都可以通过属性访问的方式来完成,这有助于使代码更加统一和易于理解。

  4. 属性访问控制:通过定义 setter 方法,你可以在设置属性值时添加一些逻辑,例如验证输入值的有效性或执行其他操作。这种属性访问控制有助于保证数据的一致性和完整性。

  5. 提高代码可维护性:将方法转化为属性可以使代码更加模块化和可维护。如果以后需要修改属性的获取方式或添加额外的逻辑,只需要修改属性的 getter 或 setter 方法,而不需要修改调用该属性的代码。

综上所述,@property 装饰器提供了一种优雅的方式来定义属性,并允许在属性访问的过程中添加额外的逻辑,从而使代码更加简洁、灵活和易于维护。

@property的方法:getter、setter 和 deleter

当使用 @property 装饰器时,可以定义三种方法来操作属性:getter、setter 和 deleter

  • Getter 方法:getter 方法用于获取属性的值。它的命名需要与 @property 装饰器的名称相同。在类中定义了 @property 装饰器的方法就是 getter 方法(默认方法)。
class MyClass:
    def __init__(self):
        self._my_attr = None

    @property
    def my_attr(self):
        return self._my_attr

在这个示例中,my_attr 方法就是属性的 getter 方法。当调用 my_instance.my_attr 时,实际上调用的是 my_attr 方法来获取属性的值。

  • Setter 方法:setter 方法用于设置属性的值。它的命名格式为 <property_name>.setter。通过在 @<property_name>.setter 装饰器下定义一个方法,可以将该方法转化为属性的 setter 方法。
class MyClass:
    def __init__(self):
        self._my_attr = None

    @property
    def my_attr(self):
        return self._my_attr
    
    @my_attr.setter
    def my_attr(self, value):
        self._my_attr = value

在这个示例中,my_attr 方法是属性的 getter 方法,而 my_attr.setter 下的 my_attr 方法是属性的 setter 方法。当调用 my_instance.my_attr = value 时,实际上调用的是 setter 方法来设置属性的值。

  • Deleter 方法:deleter 方法用于删除属性。它的命名格式为 <property_name>.deleter。通过在 @<property_name>.deleter 装饰器下定义一个方法,可以将该方法转化为属性的 deleter 方法。
class MyClass:
    def __init__(self):
        self._my_attr = None

    @property
    def my_attr(self):
        return self._my_attr
    
    @my_attr.setter
    def my_attr(self, value):
        self._my_attr = value
    
    @my_attr.deleter
    def my_attr(self):
        del self._my_attr

在这个示例中,my_attr 方法是属性的 getter 方法,my_attr.setter 下的 my_attr 方法是属性的 setter 方法,而 my_attr.deleter 下的 my_attr 方法是属性的 deleter 方法。当调用 del my_instance.my_attr 时,实际上调用的是 deleter 方法来删除属性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rs勿忘初心

你的鼓励将是我持续创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值