__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 ...
随机推荐
- 【转帖】Seccomp、BPF与容器安全
语音阅读2022-06-30 20:26 本文详细介绍了关于seccomp的相关概念,包括seccomp的发展历史.Seccomp BPF的实现原理已经与seccomp相关的一些工具等.此外,通过实例 ...
- [转帖]020 Linux 20 个宝藏命令案例
https://my.oschina.net/u/3113381/blog/5478108 1 JDK 相关的查找命令 (1)确认是否安装 JDK //命令 java -version //输出示例 ...
- 银河麒麟v10 安装 virt-manager 的过程
上个月公司购置一台飞腾2000+ 银河麒麟v10的机器. 想着能够利用虚拟化 安装一下虚拟机 提高测试灵活度 找了一下原厂要了一下相关的命令 在这里进行一下测试工作. 第一步: 安装必备的包 yum ...
- 学到了,原来 gzip 是种`连续分块`的压缩算法
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 我想要表述的是:假设有 10 mb的数据使用 gzip 算 ...
- gin启动https支持
gin是一个使用Go语言开发的Web框架,具有运行速度快,分组的路由器,良好的崩溃捕获和错误处理,支持中间件等. 在工作中有时候需要支持https服务,gin可以通过中间件的方式来提供对https的支 ...
- SqlSugar子查询
1.基础教程 1.1 API目录 *****只查一列***** //First: SqlFunc.Subqueryable<School>().Where(s => s.Id == ...
- 找工作、备考、面试刷题网站推荐(牛客网、力扣、计蒜客、hihocoder、七月在线)以及acm竞赛oj
不管是找工作笔试面试白板试进大厂,还是研究生参加初试复试,数据结构和算法都是都是重中之重,刷题就很必要,来拿走自己的offer 吧! 一.offer刷题推荐 1.牛客网 链接:牛客网 - 找工作神器| ...
- Volatility 内存数字取证方法
计算机数字取证分为内存取证和磁盘取证,活取证与死取证,不管是那种取证方式,都应尽量避免破环犯罪现场,例如通过内存转储工具对内存进行快照,通过磁盘克隆工具对磁盘进行克隆,方便后期的分析工作,这里将研究内 ...
- MySQL 字符串与时间操作函数
MariaDB [lyshark]> select Name,char_length(Name) from lyshark; -- 求字符串长度 +------------+---------- ...
- LyScript 实现Hook改写MessageBox
LyScript 可实现自定义汇编指令的替换功能,用户可以自行编写一段汇编指令,将程序中特定的通用函数进行功能改写与转向操作,此功能原理是简单的Hook操作. 插件地址:https://github. ...