关于python:Python中的描述符理解并利用其强大的功能

43次阅读

共计 2521 个字符,预计需要花费 7 分钟才能阅读完成。

Python 是一种动静类型语言,这意味着咱们能够在运行时更改对象的构造,例如增加或删除属性。然而,这种灵活性有时可能会导致问题,例如咱们可能无心中扭转了一个属性的值,或者误用了一个应该是只读的属性。为了解决这些问题,Python 提供了一个弱小的个性:描述符。

一、什么是描述符?

在 Python 中,描述符是一个实现了特定协定的对象。这个协定包含 __get__()__set__()__delete__()办法。描述符使咱们能够在拜访、设置或删除属性时定义额定的行为。

描述符次要用于治理对特定属性的拜访。当你在类中定义了一个描述符,Python 会在你拜访该属性时应用描述符中定义的行为,而不是间接拜访对象的字典。

让咱们看一个简略的例子,一个只读的描述符:

class ReadOnly:
    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        return self.val

    def __set__(self, obj, val):
        raise AttributeError(f"{self.name} is read-only")

class MyClass:
    attr = ReadOnly(10, 'attr')

在这个例子中,ReadOnly是一个描述符。当咱们尝试设置 MyClassattr属性时,它会抛出一个 AttributeError,因为attr 是只读的。

二、描述符的类型

在 Python 中,有两种类型的描述符:数据描述符和非数据描述符。

数据描述符是定义了 __set__()__delete__()办法的描述符。当一个数据描述符和一个实例字典中的项有雷同的名字时,数据描述符将具备更高的优先级。

非数据描述符只定义了 __get__() 办法。如果实例字典中有雷同名字的项,那么这个项将具备更高的优先级。

三、应用描述符

描述符通常用于实现高级性能,例如数据验证、属性拜访日志记录、类型查看等。上面咱们将实现一个简略的类型查看描述符:

class Typed:
    def __init__(self, name, required_type):
        self.name = name
        self.required_type = required_type

    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, self.required_type):
            raise TypeError(f"Expected {self.required_type}")
        instance.__dict__[self.name] = value

class MyClass:
    attr = Typed('attr', int)

在这个例子中,Typed描述符确保 attr 属性总是一个整数。如果咱们尝试设置一个非整数值,就会抛出一个TypeError

总的来说,描述符提供了一种优雅而弱小的形式来治理对象的属性。它们为数据封装、自定义数据类型、属性验证和计算属性提供了无尽的可能性。了解和应用描述符能够帮忙咱们写出更清晰、更灵便和更强壮的代码。

以下是如何应用这个 Typed 描述符的例子:

my_obj = MyClass()
my_obj.attr = 10
print(my_obj.attr)  # Output: 10

try:
    my_obj.attr = 'hello'
except TypeError as e:
    print(e)  # Output: Expected <class 'int'>

在这个例子中,你能够看到当咱们试图给 attr 赋值一个非整数值时,描述符会引发一个 TypeError。

描述符不仅能够用于类型查看,还能够用于许多其余有用的性能,例如数据绑定、读写权限管制、自动更新属性值等。当你须要在获取、设置或删除属性时执行特定的操作时,描述符可能会是一个很好的抉择。

四、描述符的高级用法

描述符的常见用法是实现属性的数据绑定和数据验证。然而,描述符还有一些高级的用法,例如提早计算和函数重载。以下是一个应用描述符实现提早计算的例子:

class LazyProperty:
    def __init__(self, function):
        self.function = function
        self.name = function.__name__

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        value = self.function(obj)
        setattr(obj, self.name, value)
        return value

class MyClass:
    @LazyProperty
    def expensive_computation(self):
        print("Computing...")
        return sum(range(1000000))

my_instance = MyClass()
print(my_instance.expensive_computation)  # Output: Computing... 499999500000
print(my_instance.expensive_computation)  # Output: 499999500000

在这个例子中,expensive_computation属性在第一次拜访时执行一次低廉的计算,之后的拜访会间接返回曾经计算出的后果。

五、描述符的局限性

尽管描述符是一个弱小的个性,但它也有一些局限性。首先,描述符只能在旧式类中应用。另外,描述符的行为依赖于其在类中的定义程序,这有时可能会导致意料之外的后果。最初,描述符对类属性的治理是全局的,无奈针对单个实例进行定制。

只管有这些局限性,描述符依然是 Python 中一个十分有用的工具。通过了解和利用描述符,咱们能够编写出更平安、更灵便的代码。

心愿这篇文章能帮忙你了解 Python 中的描述符,以及如何应用它们来进步代码的品质和灵活性。

正文完
 0