python描述器(Descriptor)
在学习Python描述器(Descriptor)之前,建议您掌握以下基础知识:
对Python面向对象编程的理解,包括类、对象、继承、多态等概念。
熟悉Python的特殊方法(也称为魔术方法)。
熟悉Python的装饰器(Decorator)的使用和原理。
了解Python中特性(Property)的概念和使用方法。
如果您对以上知识掌握得不够熟练,建议先学习相关知识再深入学习Python描述器。
【描述器官网相关链接
描述器术语 https://docs.python.org/zh-cn/3/glossary.html#term-descriptor
[描述器]定义与介绍https://docs.python.org/zh-cn/3/howto/descriptor.html#definition-and-introduction
实现描述器 https://docs.python.org/zh-cn/3/reference/datamodel.html#descriptors
描述器使用指南 https://docs.python.org/zh-cn/3/howto/descriptor.html 】
描述器(descriptor)指任何定义了 __get__(), __set__() 或 __delete__() 方法的对象。当一个类属性(attribute)为描述器时,它的特殊绑定行为就会在属性查找时被触发。通常情况下,使用 a.b 来获取、设置或删除一个属性时会在 a 的类字典中查找名称为 b 的对象,但如果 b 是一个描述器,则会调用对应的描述器方法。理解描述器的概念是更深层次理解 Python 的关键,因为这是许多重要特征(features)的基础,包括函数(unctions)、方法(methods)、特征属性(properties)、类方法(class methods)、静态方法(static methods)以及对超类(super classes)的引用等等。
描述符是一个实现动态协议(dynamic protocol)的类,该协议由__get__、__set__和__delete__方法组成。部分实现是可以的。事实上,在实际代码中看到的大多数描述符只实现__get__和__set__,而且许多描述符只实现其中一种方法。
描述器又可分为数据描述器(data descriptor)和非数据描述器(non-data descriptor),只有__get__方法的对象被称为非数据描述器(non-data desriptor),其他的都称为数据描述器(data descriptor)。描述器让对象能够自定义属性查找、存储和删除的操作。
一个简单例子代码:
# 创建一个描述器的类,它的实例就是一个描述器
# 这个类要有__get__ __set__ 这样的方法
# 这种类是当做工具使用的,不单独使用
class myDescriptor:
def __init__(self, x = 2):
self.x = x
def __get__(self, instance, owner):
return self.x
def __set__(self, instance, inputvalue):
self.x = inputvalue
# 调用描述器的类
class myCall:
dy = myDescriptor() #dy就是一个描述器
dy1 = myCall() #创建描述器实例
print(dy1) #【注1】
print(dy1.dy) #【注2】
dy1.dy = "OK" #【注3】
print(dy1.dy) #【注4】
运行输出如下:
<__main__.myCall object at 0x000001A48F910948>
2
OK
【注1】输出实例dy1的地址
【注2】输出实例dy1属性dy
【注3】改变实例dy1属性dy
【注4】输出改变后的实例dy1属性dy
Python的descriptor是一个特殊的协议,用于控制属性的访问和使用。通过实现特定的方法(__get__、__set__和__delete__),可以自定义属性的访问行为。在Python中,一个descriptor必须实现至少一个__get__、__set__或__delete__方法,这些方法组成了descriptor协议。descriptor通常与类属性一起使用,以便在对属性进行访问时触发自定义行为。以下是一个简单的例子:
#descriptor简单示例
class Celsius:
def __init__(self, value=0.0):
self.value = float(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = float(value)
class Temperature:
celsius = Celsius()
def __init__(self, initial_celsius):
self.celsius = initial_celsius
temp = Temperature(25)
print(temp.celsius) # 输出: 25.0
temp.celsius = 30
print(temp.celsius) # 输出: 30.0
在上面的例子中,我们定义了一个Celsius类,它是一个descriptor,并且包含了__get__和__set__方法。Temperature类中包含一个名为celsius的类属性,该属性是一个Celsius实例。当我们获取temp.celsius的值时,会调用Celsius类的__get__方法并返回温度值;当我们设置temp.celsius的值时,会调用Celsius类的__set__方法并更新温度。这个例子展示了如何使用Python的descriptor来自定义类属性的访问行为。
描述符是一个实现动态协议(dynamic protocol)的类,为什么Python的descriptor可以被看作是一个特殊的协议?
在Python中,一个descriptor必须实现至少一个__get__、__set__或__delete__方法,这些方法规定了如何处理对象的属性访问和修改。
当我们调用一个对象的属性时,如果这个对象定义了一个descriptor,则Python会首先调用descriptor的__get__方法来获取属性的值。如果我们对这个属性进行赋值操作,则Python会调用descriptor的__set__方法来更新属性的值。类似地,如果我们删除一个属性,则Python会调用descriptor的__delete__方法。
理解descriptor协议的重点在于,它允许我们自定义属性的访问行为,从而更好地控制属性的行为和使用方式。
Python中的descriptor用途
Descriptors in Python are special objects that allow us to customize the behavior of attribute access on an object. They can be used to implement attribute access control, data type conversion, method invocation, lazy evaluation, and caching.
Python中的descriptor是一种特殊的对象,它可以用于实现属性访问控制、数据类型转换、方法调用、延迟求值和缓存。
The main use cases of descriptors include:
其主要用途包括:
1. Implementing attribute access control: Descriptors can be used to control access to attributes, allowing us to implement read-only attributes, write-only attributes, or read-write attributes with different access control.
实现属性访问控制:通过descriptor可以对属性的读取和设置进行控制,可以实现只读属性、只写属性、读写属性等不同的访问控制。
2. Implementing data type conversion: Descriptors can be used to convert data types when reading or setting attributes, such as converting strings to numbers or numbers to strings.
实现数据类型转换:通过descriptor可以在属性读取和设置时对数据类型进行转换,比如将字符串转换为数字、将数字转换为字符串等。
3. Implementing method invocation: Descriptors can be used to make an object's method behave like an attribute of another object, allowing us to invoke methods on an object as if they were attributes.
实现方法调用:通过descriptor可以将一个对象的方法表现得像另一个对象的属性,允许我们调用对象上的方法,就好像它们是属性一样。
4. Implementing lazy evaluation: Descriptors can be used to delay the evaluation of a computation until the attribute is accessed, allowing us to implement lazy evaluation.
实现延迟计算:通过descriptor可以将一个计算过程延迟到属性访问时再执行,从而实现延迟计算的功能。
5. Implementing caching: Descriptors can be used to cache the result of a computation, avoiding redundant computation and improving performance.
实现缓存:通过descriptor可以将一个计算结果缓存起来,从而避免重复计算,提高程序性能。
In summary, descriptors are a powerful and flexible tool in Python that can be used to implement various advanced features, improving the readability, maintainability, and performance of our code.
总之,descriptor是一种非常灵活和强大的工具,可以在Python中实现各种高级功能,提高程序的可读性、可维护性和性能。
待续……
进一步学习,可参见:
Python描述器详解 https://www.cnblogs.com/JetpropelledSnake/p/8953988.html
描述器(1) https://www.dazhuanlan.com/2020/02/29/5e5965cea4d60/
描述器(descriptor) https://blog.csdn.net/a1368783069/article/details/52268049
Python黑魔法:描述器(descriptor)https://zhuanlan.zhihu.com/p/52708890