__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 ...
随机推荐
- [转帖]rsar - Extract data from plain-text sar files
sar -A -t -f /tmp/sa11 >/tmp/sar11 https://github.com/ryran/rsar When dealing with sysstat sar da ...
- Oracle 核心列信息查看与处理
Oracle 核心列信息查看与处理 背景 最近想对数据库表进行跨数据之间的比照 因为有一些自增列或者是时间戳的列不需要进行对比 后者是对比容易导致失真. 所以就准备选用其他方式进行一下处理. 本文主要 ...
- [转帖]配置logback上报日志到Skywalking
https://zhuanlan.zhihu.com/p/506119895 配置logback上报日志到Skywalking 配置logback上报日志到skywalking需要引入toolkit依 ...
- [转帖]gcc与makefile常用操作(绝对常用,也绝对够用)
makefile与gcc常用操作 一.温故知新 1.可执行程序的生成过程 2.gcc的常用操作 二.make操作 三.编写Makefile文件时常用操作 注意:在Makefile文件中 空格和缩进是完 ...
- Loki动态展示linux本地日志
Loki动态展示linux本地日志 背景 产品需要拆分微服务部署,直接使用K8S部署虽然比较规范但是部署时间较长. 本地文件系统部署简洁快速一些, 但是不太好直接复用一些规范的产品. 本次处理方法就是 ...
- linux 53端口占用的原因
解析 Linux 下 53 端口占用的现象 在 Linux 系统中,端口 53 往往是与域名解析服务(DNS)相关的.本文将详细介绍一个与端口 53 相关的情景,以及如何使用命令行工具来解析和理解这一 ...
- 说透IO多路复用模型
作者:京东零售 石朝阳 在说IO多路复用模型之前,我们先来大致了解下Linux文件系统.在Linux系统中,不论是你的鼠标,键盘,还是打印机,甚至于连接到本机的socket client端,都是以文件 ...
- 离线下载和安装UWP(windows应用商店)软件
离线下载uwp安装包 打开商店,然后搜索您要的应用程序名称,进入应用界面 点击 分享按钮,在弹出窗口中选择[复制链接] 把链接粘贴到:https://store.rg-adguard.net/ 默认选 ...
- 每日一道面试题:Java中序列化与反序列化
写在开头 哈喽大家好,在高铁上码字的感觉是真不爽啊,小桌板又拥挤,旁边的小朋友也比较的吵闹,影响思绪,但这丝毫不影响咱学习的劲头!哈哈哈,在这喧哗的车厢中,思考着这样的一个问题,Java中的对象是如何 ...
- paddle之visualDL工具使用,可视化利器。
相关链接: [一]AI Studio 项目详解[(一)VisualDL工具.环境使用说明.脚本任务.图形化任务.在线部署及预测]PARL_汀.的博客-CSDN博客 isualDL 是一个面向深度学习任 ...