c语言编程笔录

首页 >   > 笔记大全

笔记大全

Python中的描述器如何使用

更新时间:2023-11-11

Python中的描述器介绍

描述器是Python中一种特殊的协议,用于实现属性访问和对象的自定义行为。描述器主要包括三种类型:property、descriptor和protocol。简单来说,描述器就是实现了特殊的__get__, __set__和__delete__方法的类,它允许我们改变属性的读写行为、验证数据、使用智能默认值等等。

property描述器

property是Python的一种内置描述器,它能够将一个方法转换为属性,方便我们直接调用。当我们需要在获取属性值和设置属性值时进行额外的逻辑处理时,可以使用property。下面是一个简单的示例:

        class Person:
            def __init__(self, name, age):
                self.name = name
                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

        p = Person("Tom", 20)
        print(p.age)
        p.age = 30
        print(p.age)
        p.age = -10  # 抛出异常
    

descriptor描述器

descriptor是自定义的描述器,它会覆盖掉对象的属性访问,包括读取、设置和删除属性。它的行为类似于property,但是它更加灵活,可以定义更多的行为。下面给出一个简单的示例:

        class StringLength:
            def __init__(self, name):
                self.name = name

            def __get__(self, instance, cls):
                return len(getattr(instance, self.name))

            def __set__(self, instance, value):
                if not isinstance(value, str):
                    raise ValueError("String required.")
                setattr(instance, self.name, value)

        class Person:
            name = StringLength("name")
            age = 0

            def __init__(self, name, age):
                self.name = name
                self.age = age

        p = Person("Tom", 20)
        print(p.name)
        p.name = "Jerry"
        print(p.name)
        p.name = 123  # 抛出异常
    

protocol描述器

protocol是另一种描述器,它可以像方法一样调用,但是它需要实现特定的协议函数,包括__get__、__set__、__delete__、__set_name__等。这种描述器是Python 3.6中新增的特性,它提供了更加灵活的行为。下面是一个简单的示例:

        class String:
            def __init__(self):
                self.value = ""

            def __get__(self, instance, owner):
                return self.value

            def __set__(self, instance, value):
                if not isinstance(value, str):
                    raise ValueError("String required.")
                self.value = value

            def __set_name__(self, owner, name):
                self.name = name

        class Person:
            name = String()

            def __init__(self, name):
                self.name = name

        p = Person("Tom")
        print(p.name)
        p.name = "Jerry"
        print(p.name)
        p.name = 123  # 抛出异常
    

总结

在Python中,描述器是非常强大的语言特性,允许我们自定义属性的行为,并且可以实现各种有趣的功能。Python内置的property描述器实现了基本的对象属性读取和设置逻辑,而自定义的descriptor和protocol描述器则提供了更加灵活的行为,让我们可以在属性设置时执行自定义的逻辑代码。熟练掌握和运用描述器可以使我们的Pyhthon程序变得更加强大和灵活。