Python最会变魔术的魔术方法,我觉得是它

scratch变魔术 2024年12月scratch三级真题 中国电子学会 图形化编程 scratch三级真题和答案解析 ​ scratch变魔术 2024年12月电子学会图形化编程Scratch等级考试三级真题 一、题目要求 1、准备工作 (1)删除默认小猫角色,添加角色Devin和Balloon1; (2)添加Blue Sky背景。 2、功能实现 (1)点击绿旗,Devin词问“请输入你的幸运数字"; (2)输入数字个数的气球会出现在舞台上半区域的随机位置,例如输入10,10个气球出现在舞台上半区域的随机位置; (3)气球大小随机、造型随机。 阅读详情

image

猫图镇楼

在上篇文章 为什么继承 Python 内置类型会出问题? 中,我有一个核心的发现: Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系。

但是,文中也提到了一个例外:一个非常神秘的魔术方法。

这个方法非常不起眼,用途狭窄,我几乎从未注意过它,然而,当发现它可能是上述“定律”的唯一例外情况时,我认为值得再写一篇文章来详细审视一下它。

本文主要关注的问题有:

(1) missing()到底是何方神圣?

(2) missing()有什么特别之处?擅长“大变活人”魔术?

(3) missing()是否真的是上述发现的例外?如果是的话,为什么会有这种特例?

1、有点价值的__missing__()

从普通的字典中取值时,可能会出现 key 不存在的情况:

image

两种取值方法比较

对于 get() 方法,它是有返回值的,而且可以传入第二个参数,作为 key 不存在时的返回内容,因此还可以接受。但是,另外两种写法都会报错。

为了解决后两种写法的问题,就可以用到 missing() 魔术方法。

现在,假设我们有一个这样的诉求:从字典中取某个 key 对应的 value,如果有值则返回值,如果没有值则插入 key,并且给它一个默认值(例如一个空列表)。

如果用原生的 dict,并不太好实现,但是,Python 提供了一个非常好用的扩展类 collections.defaultdict :

image

defaultdict类型

如图所示,当取不存在的 key 时,没有再报 KeyError,而是默认存入到字典中。

为什么 defaultdict 可以做到这一点呢?

原因是 defaultdict 在继承了内置类型 dict 之后,还定义了一个 missing() 方法,当 __getitem__取不存在的值时,它就会调用入参中传入的工厂函数(上例是调用 list(),创建空列表)。

作为最典型的示例,defaultdict 在文档注释中写到:

image

源码实现

简而言之, missing()的主要作用就是由__getitem__在缺失 key 时调用,从而避免出现 KeyError。

另外一个典型的使用例子是 collections.Counter ,它也是 dict 的子类,在取未被统计的 key 时,返回计数 0:

image

Counter的实现

2、神出鬼没的__missing__()

由上可知,missing()在__getitem__()取不到值时会被调用,但是,我不经意间还发现了一个细节: getitem()在取不到值时,并不一定会调用__missing__()。

这是因为它并非内置类型的必要属性,并没有在字典基类中被预先定义。

如果你直接从 dict 类型中取该属性值,会报属性不存在: AttributeError: type object ‘object’ has no attribute ‘missing’ 。

使用 dir() 查看,发现确实不存在该属性:

image

属性报错

如果从 dict 的父类即 object 中查看,也会发现同样的结果。

这是怎么回事呢?为什么在 dict 和 object 中都没有__missing__属性呢?

然而,查阅最新的官方文档,object 中分明包含这个属性:

image

官方文档

出处:https://docs.python.org/3/reference/datamodel.html?highlight=missing#object.missing

也就是说,理论上 object 类中会预定义__missing__,其文档证明了这一点,然而实际上它并没有被定义!文档与现实出现了偏差!

如此一来,当 dict 的子类(例如 defaultdict 和 Counter)在定义__missing__ 时,这个魔术方法事实上只属于该子类,也就是说, 它是一个诞生于子类中的魔术方法!

据此,我有一个不成熟的猜想:getitem()会判断当前对象是否是 dict 的子类,且是否拥有__missing__(),然后才会去调用它(如果父类中也有该方法,则不会先作判断,而是直接就调用了)。

我在交流群里说出了这个猜想,有同学很快在 CPython 源码中找到验证:

image

CPython源码

而这就有意思了, **在内置类型的子类上才存在的魔术方法, **纵观整个 Python 世界,恐怕再难以找出第二例。

我突然有一个联想:这神出鬼没的__missing__(),就像是一个擅长玩“大变活人”的魔术师,先让观众在外面透过玻璃看到他(即官方文档),然而揭开门时,他并不在里面(即内置类型),再变换一下道具,他又完好无损就出现了(即 dict 的子类)。

3、被施魔法的__missing__()

missing() 的神奇之处,除了它本身会变“魔术”之外,它还需要一股强大的“魔法”才能驱动。

在 上篇文章 中,我发现原生的魔术方法间相互独立,它们在 C 语言界面可能有相同的核心逻辑,但是在 Python 语言界面,却并不存在着调用关系:

image

魔术方法的调用关系

魔术方法的这种“老死不相往来”的表现,违背了一般的代码复用原则,也是导致内置类型的子类会出现某些奇怪表现的原因。

官方 Python 宁肯提供新的 UserString、UserList、UserDict 子类,也不愿意复用魔术方法,唯一合理的解释似乎是令魔术方法相互调用的代价太大。

但是,对于特例__missing__(),Python 却不得不妥协,不得不付出这种代价!

missing() 是魔术方法的“ **二等公民 **”,它没有独立的调用入口,只能被动地由 getitem() 调用,即__missing__() 依赖于__getitem__()。

不同于那些“ **一等公民 **”,例如 init()、enter()、len()、eq() 等等,它们要么是在对象生命周期或执行过程的某个节点被触发,要么由某个内置函数或操作符触发,这些都是相对独立的事件,无所依赖。

missing() 依赖于__getitem__(),才能实现方法调用;而 getitem() 也要依赖 missing(),才能实现完整功能。

为了实现这一点,getitem()在解释器代码中开了个后门,从 C 语言界面折返回 Python 界面,去调用那个名为“missing”的特定方法。

image

missing的魔法

而这就是真正的“魔法”了,目前为止,missing()似乎是唯一一个享受了此等待遇的魔术方法!

4、小结

Python 的字典提供了两种取值的内置方法,即__getitem__() 和 get(),当取值不存在时,它们的处理策略是不一样的: 前者会报错 KeyError ,而后者会返回 None。

为什么 Python 要提供两个不同的方法呢?或者应该问,为什么 Python 要令这两个方法做出不一样的处理呢?

这可能有一个很复杂(也可能是很简单)的解释,本文暂不深究了。

不过有一点是可以确定的:即原生 dict 类型简单粗暴地抛 KeyError 的做法有所不足。

为了让字典类型有更强大的表现(或者说让__getitem__()作出 get() 那样的表现),Python 让字典的子类可以定义__missing__(),供__getitem__()查找调用。

本文梳理了__missing__()的实现原理,从而揭示出它并非是一个毫不起眼的存在,恰恰相反, 它是唯一一个打破了魔术方法间壁垒,支持被其它魔术方法调用的特例!

Python 为了维持魔术方法的独立性,不惜煞费苦心地引入了 UserString、UserList、UserDict 这些派生类,但是对于 missing(),它却选择了妥协。

本文揭示出了这个魔术方法的神秘之处,不知你读后有何感想呢?欢迎留言讨论。

写在最后:本文属于“Python为什么”系列(Python猫出品),该系列主要关注 Python 的语法、设计和发展等话题,以一个个“为什么”式的问题为切入点,试着展现 Python 的迷人魅力,欢迎关注!

如果真的遇到好的同事,那算你走运,加油,抓紧学到手。

python分享企鹅圈: 1055012877

包含python, 爬虫等人工智能软件,以及爬虫、网络安全、全自动办公的编程方法。

打造从零基础到项目开发上手实战全方位解析!

点击加入

PCB_Project.PrjPcb 4 Not in version control Altium Designer中PCB项目出现"NOT in version control"错误的解决方法:1. 禁用不需要的版本控制集成(DXP→Preferences→Version Control);2. 清理项目缓存(Projects面板右键→Clean Project);3. 检查文件读写权限;4. 如无效可新建项目重新添加文件。如需使用SVN版本控制,需正确配置SVN客户端路径,创建或连接SVN仓库,并将项目文件提交至版本控制系统。注意新建SVN仓库必须使用空目录,建议使用 阅读详情

相关推荐

IBIS模型中的Pullup和Pulldown曲线详解:如何避免信号完整性设计中的常见错误

本文深入解析IBIS模型中Pullup和Pulldown曲线的关键作用,揭示其在信号完整性设计中的黄金法则。通过详细分析曲线特性、常见误区及验证方法,帮助工程师避免设计错误,优化高速PCB设计。文章还展示了曲线数据在动态终端匹配、串扰预测和电源完整性分析中的高级应用,提升设计效率和可靠性。

weixin_30275415的博客 452

python + Qt5 + opengl 绘制魔方(一)

今天开始记录一下整个魔方的具体绘制过程,虽然没有用到太多的很深的技术,但是做这个魔方的过程,确实是一个自我学习的过程,涉及到每一个细节,算法,然后到每一个小功能的实现,从在脑瓜里的一个偶然的想法,到最终实现它,从无到有,都很有成就感。 首要问题是绘制魔方的容器。看了一些教程,好多都是用OpenGL的GLUT库在一个独立的窗口中显示模型,无法添加一些按钮等进行交互,个人感觉不太方便,于是考虑用QT Designer设计加载一个Widget进行显示。 一、绘图环境准备 python的环境设置:pych..

humgre的博客 3803

MOOS-ivp实战:从零搭建水下机器人通信系统(Ubuntu 22.04版)

本文详细介绍了在Ubuntu 22.04系统上从零开始搭建MOOS-ivp水下机器人通信系统的完整实战流程。内容涵盖环境准备、核心安装、MOOSDB通信模型解析、自定义应用节点开发、以及调试监控工具链的使用,旨在帮助开发者快速掌握这一分布式机器人系统框架,构建稳定可靠的水下机器人通信与控制系统。

snow3的博客 636

Python最会变魔术的魔术方法,我觉得是它!

作者:豌豆花下猫来源:Python猫我有一个核心的发现:Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系。 但是,文中也...

cainiao_python的博客 203

【论文精读】Latent Diffusion

Latent Diffusion

weixin_44934783的博客 4479

18、近端策略优化(PPO)算法详解

本文详细介绍了近端策略优化(PPO)算法的理论基础、算法流程、实现方法及实际应用。PPO作为当前最受欢迎的策略梯度算法之一,具有易于实现、计算成本低、样本效率高和性能优越等优点。文章对比了基于自适应KL惩罚和基于裁剪目标的两种PPO变体,重点解析了裁剪目标函数的设计原理及其在Actor-Critic框架下的实现方式,并通过Atari Pong游戏展示了完整的训练配置与流程。最后总结了PPO的优势、适用场景及未来发展方向,为强化学习研究者和实践者提供了全面的参考。

mongodb5scout的博客 182

Python 魔术方法(Magic Method)

介绍在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”,例如类的初始化方法 __init__,Python中所有的魔术方法均在官方文档中有相应描述,但是对于官方的描述比较混乱而且组织比较松散。很难找到有一个例子。构造和初始化每个Pythoner都知道一个最基本的魔术方法, __init__ 。通过此方法我们可以定义一个对象的初始操作。然而,当调用 x = S...

zxy569493432的博客 248

ORB-SLAM2算法部署验证、原理代码和各种改进方法汇总

本文主要汇总个人学习使用ORB-SLAM2算法中参考的相关博客和代码汇总,以及在ORB-SLAM2算法基础上各个改进方法的汇总。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 745

怎样用Python控制图片人物动起来?一文就能Get!

作者 | 李秋键责编 | 李雪敬头图 | 优快云 下载自视觉中国出品 | AI科技大本营(ID:rgznai100)引言:近段时间,一个让梦娜丽莎图像动起来的项目火遍了朋友圈。而今天我...

AI科技大本营 6345

国产麒麟V10系统命令大全,100个实用命令助你玩转系统!

国产麒麟V10系统命令大全,100个实用命令助你玩转系统!

网络技术联盟站 1914

Multisim14.0仿真(五十九)基于74LS161的24进制计数器应用设计

它具有同步预置、异步清零功能,支持并行数据加载,并可在计数使能控制下进行二进制计数。:低电平时,在下一个时钟上升沿加载输入数据(A, B, C, D)。(多个 74LS161D 串联构成 8 位、12 位等更长计数器)。低电平时,下一个时钟上升沿加载输入数据(A, B, C, D)。:低电平有效,立即清零计数器(不受时钟控制)。均为高电平时,每个时钟上升沿计数。:两者均为高电平时,计数器才能递增。:立即清零计数器(不受时钟控制)。(通过预置初始值控制计数范围)。(计数范围:0 ~ 15,即。

corlin6688的博客 4766

机器学习python基础(一)魔法命令

文章目录魔法命令%timeit%run其他魔法命令 接下去几篇将讲解机器学习需要用到的python的基础,主要为numpy、matplotlib等关于统计库和一些常用命令的实践。 本文主要讲解一些魔法命令。 魔法命令 %timeit 这个命令用来计算代码的执行效率的。 代表执行了1000次,时间的效率是每次303us左右,标准差2.63us。 如果把数量加大,时间边长,那么就只执行一次了: %...

翻身咸鱼的博客 1889

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Python最会变魔术的魔术方法,竟能“大变活人“

我有一个核心的发现:Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系。 但是,文中也提到了一个例外:一个非常神秘的魔术方法。 这个方法非常不起眼,用途狭窄,我几乎从未注意过它,然而,当发现它可能是上述“定律”的唯一例外情况时,我认为值得再写一篇文章来详细审视一下它。 本文主要关注的问题有: (1) __missing__()到底是何方神圣? (2) __missing__()有什么特别之处?擅长“大变活人”魔术? (3)...

387

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

当时那个input都有值调用方法_Python最会变魔术的魔术方法,我觉得是它

猫图镇楼在上篇文章 为什么继承 Python 内置类型会出问题?中,我有一个核心的发现:Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系。但是,文中也提到了一个例外:一个非常神秘的魔术方法。这个方法非常不起眼,用途狭窄,我几乎从未注意过它,然而,当发现它可能是上述“定律”的唯一例外情况时,我认为值得再写一篇文章来详细审视一下它。本文...

weixin_39649736的博客 83

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

python创建实例会调用哪些魔术方法_Python最会变魔术的魔术方法,我觉得是它!...

作者:豌豆花下猫来源:Python猫在,我有一个核心的发现:Python 内置类型的特殊方法(含魔术方法与其它方法)由 C 语言独立实现,在 Python 层面不存在调用关系。但是,文中也提到了一个例外:一个非常神秘的魔术方法。这个方法非常不起眼,用途狭窄,我几乎从未注意过它,然而,当发现它可能是上述“定律”的唯一例外情况时,我认为值得再写一篇文章来详细审视一下它。本文主要关注的问题有:(1) _...

weixin_42361611的博客 152

会变 "魔术" 的 Python_用python变魔术(1)

列表也可以相加那么两个对象(这里特指类的实例对象)可不可以相加呢?上面用 Point 类表示坐标系中的一个点,x,y 分别代表横轴和纵轴,两个点相加时报错了,错误日志告诉我们,对于 Point 类不支持 「+」操作。但如果你实现了魔术方法 __add__ 就可以支持加操作了再来运行:再举一个例子我们知道类的属性一般都是用点操作获取属性,例如p.x,p.y,而访问字典对应的key值都是通过 p[‘x’] 或者 p.get(“x”) 来访问的,那字典可不可以用 “.” 的方式获取呢?

2401_84141337的博客 286

会变魔术的 OpenCV_01 简介与安装

OpenCV是计算机视觉中经典的专用库,使用conda命令行进行安装opencv-python 以及 opencv-contrib-python,最后再调用函数验证是否安装成功

A_John 的博客 999

会变 "魔术" 的 Python

Python 最吸引你的地方是什么? 整洁的代码缩进格式?丰富的第三方包?更高的开发效率?还是良好的跨平台性? 这些特性都不足以说明 Python 的优点,最吸引人的应该是动态性所带来的灵活与便利性。 你可能听过说一个词叫做「鸭子类型」,所谓鸭子类型就是只要它走路像鸭子,叫起来像鸭子,那么你就可以认为它是鸭子。 而 Python 就有这种魔力使得任何东西都可以是鸭子,这种魔力就源自于语言的...

python学习者的博客 483

60行python代码带你了解刘谦春晚魔术的奥秘

60行python代码带你了解刘谦春晚魔术的奥秘

海哥python的博客 1255

Python中常见的魔术方法

在Python中,魔术方法(Magic methods)是指在类定义中以双下划线(__)开头和结尾的方法。这些方法在Python中具有特殊的意义,它们提供了一种定制类的行为的机制。

qq_45711921的博客 641
上一篇: Python多线程你真的会吗?一文帮你理清如何join线程
下一篇: 不会python的人,真的拿不到offer吗?
Python文泽老师
博客等级 码龄7年 1320粉丝 278原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值