__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
												
											__set_name__魔法方法的更多相关文章
- PHP的魔法方法__set() __get()
		
php的魔法方法__set()与__get() Tags: PHP 我们先来看看官方的文档如何定义他们的: public void __set(string $name, mixed $value); ...
 - python进阶(四)---需要了解的魔法方法
		
以下内容,源于个人理解所得,纯属臆测,爱信不信:-D.欢迎大家留言讨论指正. 1.__new__魔法方法: 原型:__new__(cls, *args, **kwargs) 说明:__new__魔法方 ...
 - Python中的魔法方法
		
1.什么是魔法方法? 魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一 ...
 - Python的魔法方法 .
		
基本行为和属性 __init__(self[,....])构造函数 . 在实例化对象的时候会自动运行 __del__(self)析构函数 . 在对象被回收机制回收的时候会被调用 __str__(sel ...
 - 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器
		
准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here ...
 - python 魔法方法
		
I am not a creator, I just a porter. Note: Everything is object in python. 对于Python来说一切都是对象,也就是函数的参数 ...
 - Python学习笔记:06魔法方法和迭代器
		
魔法方法,属性和迭代器 新式类 通过赋值语句__metaclass=true或者class NewStyle(object)继承内建类object,可以表明是新式类. 构造方法 对象被创建后,会立即调 ...
 - 魔法方法:算术运算 - 零基础入门学习Python042
		
魔法方法:算术运算 让编程改变世界 Change the world by program 我现在重新提一个名词:工厂函数,不知道大家还有没有印象?我们在老早前就提到过Ta,由于那时候我们还没有学习类 ...
 - 魔法方法:构造和析构 - 零基础入门学习Python041
		
魔法方法:构造和析构 让编程改变世界 Change the world by program 构造和析构 什么是魔法方法呢?我们来系统总结下: - 魔法方法总是被双下划线包围,例如__init__ - ...
 - python 魔法方法之:__getitem__ __setitem__ __delitem__
		
h2 { color: #fff; background-color: #7CCD7C; padding: 3px; margin: 10px 0px } h3 { color: #fff; back ...
 
随机推荐
- [转帖]Linux-计算毫秒数
			
https://www.cnblogs.com/yeyuzhuanjia/p/15822653.html date +%s返回自划时代以来的秒数. date +%s%N返回秒数+当前纳秒数. 因此,e ...
 - [转帖]skywalking配置nacos集群模式
			
版本: name version nacos 1.1.0 skywalking 6.2.0 elasticsearch 6.3.2 es集群管理工具 cerebro-0.8.3 https://git ...
 - [转帖]Linux:页表中PGD、PUD、PMD、TLB等概念介绍
			
1.PGD: Page Global Directory Linux系统中每个进程对应用户空间的pgd是不一样的,但是linux内核 的pgd是一样的.当创建一个新的进程时,都要为新进程 ...
 - [转帖]记录几个常用linux命令的使用方法——find、grep、file、which、whereis和压缩命令gzip、bzip2、tar
			
一.命令1: find.grep.file.which.whereis 1.find 目的:查找符合条件的文件 1)在哪些目录中查找 2)查找的内容 格式: find 目录名 选项 查找条件 举例: ...
 - Go 跟踪函数调用链,理解代码更直观
			
Go 跟踪函数调用链,理解代码更直观 目录 Go 跟踪函数调用链,理解代码更直观 一.引入 二.自动获取所跟踪函数的函数名 三.增加 Goroutine 标识 四.让输出的跟踪信息更具层次感 五.利用 ...
 - Docker中Nginx部署go应用
			
docker配合Nginx部署go应用 Nginx 名词解释 正向代理 反向代理 构建镜像 Nginx镜像 配置nginx.conf server_name Nginx中的负载均衡 轮询 upstre ...
 - Python 探索性数据分析工具(PandasGUI,Pandas Profiling,Sweetviz,dtale)以及学术论文快速作图science.mplstyle
			
如果探索的数据集侧重数据展示,可以选PandasGUI:如果只是简单了解基本统计指标,可以选择Pandas Profiling和Sweetviz:如果需要做深度的数据探索,那就选择dtale. 1. ...
 - 数据挖掘机器学习[五]---汽车交易价格预测详细版本{模型融合(Stacking、Blending、Bagging和Boosting)}
			
题目出自阿里天池赛题链接:零基础入门数据挖掘 - 二手车交易价格预测-天池大赛-阿里云天池 相关文章: 特征工程详解及实战项目[参考] 数据挖掘---汽车车交易价格预测[一](测评指标:EDA) 数据 ...
 - 数据挖掘机器学习[二]---汽车交易价格预测详细版本{EDA-数据探索性分析}
			
题目出自阿里天池赛题链接:零基础入门数据挖掘 - 二手车交易价格预测-天池大赛-阿里云天池 相关文章: 特征工程详解及实战项目[参考] 数据挖掘---汽车车交易价格预测[一](测评指标:EDA) 数据 ...
 - 深入浅出Java多线程(三):线程与线程组
			
「引言」 大家好,我是你们的老伙计秀才!今天带来的是[深入浅出Java多线程]系列的第三篇内容:线程与线程组.大家觉得有用请点赞,喜欢请关注!秀才在此谢过大家了!!! 在现代软件开发中,多线程编程已成 ...