描述符是python中用于自定义属性访问行为的对象,其核心在于实现__get__、__set__和__delete__方法。1. __get__用于获取属性值,当访问属性时触发;2. __set__用于设置属性值,控制赋值过程;3. __delete__用于删除属性。描述符必须作为类属性存在才生效,且数据描述符(含__set__或__delete__)优先级高于实例字典。若将值存储在描述符自身,会导致所有实例共享该值,应避免此做法。掌握描述符机制有助于深入理解属性访问、装饰器及property等内置工具的实现原理,并可用于高级特性如类型检查和自动属性管理。
在Python中,描述符(Descriptor)是一种实现特定协议的对象,这个协议包含 __get__、__set__ 和 __delete__ 方法。通过这些方法,我们可以自定义类属性的访问行为。理解描述符的工作机制,有助于更深入掌握属性访问、装饰器、以及像 property 这样的内置工具背后的原理。
描述符的核心在于它定义了如何通过类或实例访问属性。一个对象只要实现了以下任意一个方法,就可以被称为描述符:
__get__(self, instance, owner):用于获取属性值。__set__(self, instance, value):用于设置属性值。__delete__(self, instance):用于删除属性。这些方法中的参数含义如下:
self:描述符实例本身。instance:使用该描述符的类实例(如果是通过实例访问的话)。owner:使用该描述符的类(即实例所属的类)。比如,当你访问 obj.attr 时,如果 attr 是一个描述符对象,那么实际上会调用它的 __get__ 方法。
立即学习“Python免费学习笔记(深入)”;
__get__ 的工作方式当访问某个属性时,Python解释器会在类和实例的命名空间中查找该属性。如果找到的是一个实现了 __get__ 的对象,并且这个对象是“数据描述符”(有 __set__ 或 __delete__)或者“非数据描述符”,那么就会触发 __get__ 方法。
举个例子:
class MyDescriptor:
def __get__(self, instance, owner):
print("Getting value")
return 42
class MyClass:
attr = MyDescriptor()
obj = MyClass()
print(obj.attr)输出为:
Getting value 42
在这个例子中,访问 obj.attr 实际上调用了 MyDescriptor.__get__ 方法。这里的关键点是,描述符必须作为类属性存在于另一个类中才会生效,不能直接赋值给实例属性。
__set__ 的作用与限制如果你希望描述符可以控制属性的赋值过程,就需要实现 __set__ 方法。这个方法会在你执行类似 obj.attr = value 的操作时被调用。
来看一个简单的实现:
class MyDescriptor:
def __get__(self, instance, owner):
print("Getting value")
return self.value
def __set__(self, instance, value):
print("Setting value")
self.value = value
class MyClass:
attr = MyDescriptor()
obj = MyClass()
obj.attr = 100
print(obj.attr)输出:
Setting value Getting value 100
注意几点:
__set__,那它就是一个“非数据描述符”,这时候实例字典中可以直接覆盖这个属性。__get__ 和 __set__,它就是“数据描述符”,这时实例字典中的同名属性会被忽略。__set__ 方法通常会把值保存在实例上而不是描述符自身,否则多个实例共享同一个值。例如,在上面的例子中,如果我们想让每个 MyClass 实例都有自己的值,应该把值存在 instance 上:
def __set__(self, instance, value):
instance._value = value
def __get__(self, instance, owner):
return instance._value这样就能避免不同实例之间的值互相干扰。
使用描述符时有几个常见的坑需要注意:
__get__ 或 __set__ 中不小心修改了自身属性,可能会导致无限递归。基本上就这些内容了。描述符是Python底层机制的一部分,虽然不常用,但在实现高级特性如类型检查、自动属性管理等方面非常有用。掌握其原理,能让你写出更灵活、可控的类设计。
以上就是Python中描述符protocol 描述符协议__get__和__set__实现原理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号