隐藏页面特效

__set_name__魔法方法

介绍

__set_name__ 方法是 Python 3.6 中引入的一种特殊方法,它可以在类属性被赋值时自动调用。这个方法可以用来处理类属性的名称绑定问题,例如将类属性与其所在的类进行绑定。 具体来说,当一个类定义了一个描述符(descriptor)并将其作为类属性时,Python 将在该类定义完成后自动调用描述符的 __set_name__ 方法,并将该类属性的名称作为参数传递给该方法。这样,我们就可以在 __set_name__ 方法中访问该类属性的名称,并将其与描述符进行绑定。

示例

class Descriptor: def __set_name__(self, owner, name): print(f"Descriptor.__set_name__(owner={owner}, name={name})") def __get__(self, instance, owner): print(f"Descriptor.__get__(instance={instance}, owner={owner})") return instance.__dict__.get(self.name) def __set__(self, instance, value): print(f"Descriptor.__set__(instance={instance}, value={value})") instance.__dict__[self.name] = value class MyClass: my_attr = Descriptor()

代码分析

在这个示例中,我们定义了一个名为 Descriptor 的类,它实现了描述符协议(即包含 __get____set__ __delete__ 方法)。然后,我们定义了一个名为 MyClass 的类,并将 Descriptor 实例作为其类属性 my_attr 的值。 Python 解释器执行到 MyClass 类定义结束时,它会自动调用 Descriptor.__set_name__() 方法,并将 MyClass 类和属性名 my_attr 作为参数传递给该方法。在本例中,我们只是简单地打印了一条消息来演示 __set_name__ 方法的调用时机。 接下来,当我们创建 MyClass 实例并访问其 my_attr 属性时,Python 将自动调用描述符的 __get__ __set__ 方法,并分别输出相应的消息以演示这些方法的调用时机。

代码示例

from typing import Callable, Any class Validation: def __init__( self, validation_function: Callable[[Any], bool], error_msg: str ) -> None: print("Validation初始化被执行") self.validation_function = validation_function # 传进来的是匿名函数 self.error_msg = error_msg def __call__(self, value): print("call被执行") if not self.validation_function(value): # lambda x: isinstance(x, (int, float)) raise ValueError(f"{value!r} {self.error_msg}") class Field: # 描述符类 def __init__(self, *validations): # 用*接收,表示可以传多个,目前代码可以理解为传进来的就是一个个Validation的实例 print("Field初始化被执行") self._name = None self.validations = validations # 接收完后的类型是元组 def __set_name__(self, owner, name): print("set_name被执行") self._name = name # 会自动将托管类ClientClass的类属性descriptor带过来 def __get__(self, instance, owner): print("get被执行") if instance is None: return self return instance.__dict__[self._name] def validate(self, value): print("验证被执行") for validation in self.validations: validation(value) # 这是是将对象当成函数执行时,调用Validation的__call__魔法方法 def __set__(self, instance, value): """ :param self: 指的是Field对象 :param instance: ClientClass对象 :param value: 给属性赋值的值 :return: """ print("set被执行") self.validate(value) instance.__dict__[self._name] = value # 给ClientClass对象赋值 {"descriptor": 42} class ClientClass: # 托管类 descriptor = Field( Validation(lambda x: isinstance(x, (int, float)), "is not a number"), # Validation(lambda x: x >= 0, "is not >= 0"), ) if __name__ == '__main__': """ Validation初始化被执行 Field初始化被执行 set_name被执行 # 当Field()赋值给descriptor变量时,执行__set_name__ --------------------- set被执行 验证被执行 call被执行 """ client = ClientClass() # 实例化对象 print("---------------------") # 给上面实例化的对象中的属性(Field实例化对象)赋值为42 client.descriptor = 42

__EOF__

本文作者404 Not Found
本文链接https://www.cnblogs.com/weiweivip666/p/17299024.html
关于博主:可能又在睡觉
版权声明:转载请注明出处
声援博主:如果看到我睡觉请喊我去学习
posted @   我在路上回头看  阅读(735)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示