漫谈Python魔术方法,见过的没见过的都在这里了
漫谈Python魔术方法,见过的没见过的都在这里了
就说一下,不深入
假的一览
- 提到魔术方法,学过python都应该知道一些。至少你得会__init__吧。
 - 在我之前写的博文中有很多都涉及魔术方法。比如
- 浅谈Python中的if,可能有你不知道的,涉及
__bool__和__len__ - 浅谈Python中的in,可能有你不知道的,涉及
__contains__,__iter__,__getitem__ - Python常见面试题007. 谈谈Python中__init__和__new__的区别
 
 - 浅谈Python中的if,可能有你不知道的,涉及
 - 在《Python源码剖析》中做了个简单的概括(侵删),但仍然是不全的
 

数据模型
https://docs.python.org/zh-cn/3.9/reference/datamodel.html#special-method-names
以3.9为例
- 最全的还是在官方(但仍然会有漏网之鱼)
 - 我稍作整理,仅供参考
 
1. ★基本定制
| 方法 | 说明 | 
|---|---|
__init__(self[, ...]) | 
所谓的初始化,在实例 (通过__new__) 被创建之后,返回调用者之前调用 | 
__new__(cls[, ...]) | 
调用以创建一个 cls 类的新实例 | 
__del__(self) | 
在实例将被销毁时调用。 这还被称为终结器或析构器(不适当) | 
__repr__(self) | 
由 repr() 内置函数调用以输出一个对象的“官方”字符串表示 | 
__str__(self) | 
通过 str(object) 以及内置函数 format() 和 print() 调用以生成一个对象的“非正式”或格式良好的字符串表示 | 
__bytes__(self) | 
通过 bytes 调用以生成一个对象的字节串表示 | 
__format__(self,format_spec) | 
通过 format() 内置函数、扩展、格式化字符串字面值 的求值以及 str.format() 方法调用以生成一个对象的“格式化”字符串表示 | 
__hash__(self) | 
通过内置函数 hash() 调用以对哈希集的成员进行操作,属于哈希集的类型包括 set、frozenset 以及 dict。__hash__() 应该返回一个整数 | 
__bool__(self) | 
调用此方法以实现真值检测以及内置的 bool() 操作;应该返回 False 或 True | 
2. 富比较方法
| 方法 | 说明 | 
|---|---|
__lt__(self, other) | 
小于 | 
__le__(self, other) | 
小于等于 | 
__eq__(self, other) | 
等于 | 
__ne__(self, other) | 
不等于 | 
__gt__(self, other) | 
大于 | 
__ge__(self, other) | 
大于等于 | 
3. ★自定义属性访问
| 方法 | 说明 | 
|---|---|
__getattr__(self, name) | 
当默认属性访问因引发 AttributeError 而失败时被调用 | 
__getattribute__(self, name) | 
此方法会无条件地被调用以实现对类实例属性的访问 | 
__setattr__(self, name, value) | 
此方法在一个属性被尝试赋值时被调用 | 
__delattr__(self, name) | 
类似于 __setattr__() 但其作用为删除而非赋值 | 
__dir__(self) | 
此方法会在对相应对象调用 dir() 时被调用 | 
4. ★实现描述器
| 方法 | 说明 | 
|---|---|
__get__(self, instance, owner=None) | 
调用此方法以获取所有者类的属性(类属性访问)或该类的实例的属性(实例属性访问) | 
__set__(self, instance, value) | 
用此方法以设置 instance 指定的所有者类的实例的属性为新值 value。 | 
__delete__(self, instance) | 
调用此方法以删除 instance 指定的所有者类的实例的属性。 | 
__set_name__(self, owner, name) | 
在所有者类 owner 创建时被调用。描述器会被赋值给 name。 | 
5. 自定义类创建
| 方法 | 说明 | 
|---|---|
__init_subclass__(cls)  | 
当所在类派生子类时此方法就会被调用 | 
6. 自定义实例及子类检查
| 方法 | 说明 | 
|---|---|
__instancecheck__(self, instance) | 
如果 instance 应被视为 class 的一个(直接或间接)实例则返回真值 | 
__subclasscheck__(self, subclass) | 
如果 subclass 应被视为 class 的一个(直接或间接)子类则返回真值 | 
7. 模拟泛型类型
| 方法 | 说明 | 
|---|---|
__class_getitem__(cls, key) | 
按照 key 参数指定的类型返回一个表示泛型类的专门化对象。 | 
- 当在类上定义时,
__class_getitem__()会自动成为类方法。 因此,当它被定义时没有必要使用@classmethod来装饰。 
8. ★模拟可调用对象
| 方法 | 说明 | 
|---|---|
__call__(self[, args...]) | 
此方法会在实例作为一个函数被“调用”时被调用 | 
9. ★模拟容器类型
| 方法 | 说明 | 
|---|---|
__len__(self) | 
调用此方法以实现内置函数 len()。应该返回对象的长度 | 
__length_hint__(self) | 
调用此方法以实现 operator.length_hint()。 应该返回对象长度的估计值(可能大于或小于实际长度) | 
__getitem__(self, key) | 
调用此方法以实现 self[key] 的取值(注:官文是未付,英文是evaluation) | 
__setitem__(self, key, value) | 
调用此方法以实现向 self[key] 赋值 | 
__delitem__(self, key) | 
调用此方法以实现 self[key] 的删除 | 
__missing__(self, key) | 
此方法由 dict.__getitem__() 在找不到字典中的键时调用以实现 dict 子类的 self[key] | 
__iter__(self) | 
此方法在需要为容器创建迭代器时被调用 | 
__reversed__(self) | 
此方法(如果存在)会被 reversed() 内置函数调用以实现逆向迭代 | 
__contains__(self, item) | 
调用此方法以实现成员检测运算符in | 
10. ★模拟数字类型
| 方法 | 说明 | 
|---|---|
__add__(self, other) | 
+ | 
__sub__(self, other) | 
- | 
__mul__(self, other) | 
* | 
__matmul__(self, other) | 
@这个你可能没听过 | 
__truediv__(self, other) | 
除法 / | 
__floordiv__(self, other) | 
地板除 // | 
__mod__(self, other) | 
取余 % | 
__pow__(self, other[,modulo]) | 
幂运算 ** | 
__lshift__(self, other) | 
左移 << | 
__rshift__(self, other) | 
右移 >> | 
__and__(self, other) | 
& 与 | 
__xor__(self, other) | 
^ 异或 | 
__or__(self, other) | 
| 或 | 
- 上面的方法再加个r又是另外一大类
 
| 方法 | 说明 | 
|---|---|
__radd__(self, other) | 
+ | 
__rsub__(self, other) | 
- | 
__rmul__(self, other) | 
* | 
__rmatmul__(self, other) | 
@ | 
| `rtruediv(self, other) | / | 
__rfloordiv__(self, other) | 
// | 
__rmod__(self, other) | 
取余 % | 
__rpow__(self, other[,modulo]) | 
幂运算 ** | 
__rlshift__(self, other) | 
左移 << | 
__rrshift__(self, other) | 
右移 >> | 
__rand__(self, other) | 
& | 
__rxor__(self, other) | 
^ | 
__ror__(self, other) | 
| | 
调用这些方法来实现具有反射(交换)操作数的二进制算术运算 (
+,-,*,@,/,//,%,divmod(),pow(),**,<<,>>,&,^,|)。这些成员函数仅会在左操作数不支持相应运算 3 且两个操作数类型不同时被调用。4 例如,求表达式x - y的值,其中 y 是具有__rsub__()方法的类的一个实例,则当x.__sub__(y)返回 NotImplemented 时会调用y.__rsub__(x)。请注意三元版的
pow()并不会尝试调用__rpow__()(因为强制转换规则会太过复杂)
- 加个i又是另外一套
 
| 方法 | 说明 | 
|---|---|
__iadd__(self, other) | 
+= | 
__isub__(self, other) | 
-= | 
__imul__(self, other) | 
*= | 
__imatmul__(self, other) | 
@= | 
__itruediv__(self, other) | 
/= | 
__ifloordiv__(self, other) | 
//= | 
__imod__(self, other) | 
%= | 
__ipow__(self, other[,modulo]) | 
**= | 
__ilshift__(self, other) | 
<<= | 
__irshift__(self, other) | 
>>= | 
__iand__(self, other) | 
&= | 
__ixor__(self, other) | 
^= | 
__ior__(self, other) | 
|= | 
- 调用上面这些方法来实现扩展算术赋值
 
- 数字是最多的
 - 不光上面的,还要一些
 
| 方法 | 说明 | 
|---|---|
__neg__(self) | 
一元运算符 - | 
__pos__(self) | 
一元运算符 + | 
__abs__(self) | 
abs() | 
__invert__(self) | 
一元运算符 ~ | 
__complex__(self) | 
实现内置函数complex() | 
__int__(self) | 
实现内置函数int() | 
__float__(self) | 
实现内置函数float() | 
__index__(self) | 
调用此方法以实现 operator.index() | 
__round__(self[,ndigits]) | 
实现内置函数round() | 
__trunc__(self) | 
实现内置函数trunc() | 
__floor__(self) | 
实现内置函数floor() | 
__ceil__(self) | 
实现内置函数ceil() | 
11. 上下文管理器
| 方法 | 说明 | 
|---|---|
__enter__(self) | 
进入与此对象相关的运行时上下文 | 
__exit__(self, exc_type, exc_value, traceback) | 
退出关联到此对象的运行时上下文 | 
12. 协程相关
可等待对象
| 方法 | 说明 | 
|---|---|
__await__(self) | 
awaitable 对象主要实现了该方法,它必须返回一个 iterator | 
异步迭代器
| 方法 | 说明 | 
|---|---|
__aiter__(self) | 
必须返回一个 异步迭代器 对象 | 
__anext__(self) | 
必须返回一个 可迭代对象 输出迭代器的下一结果值 | 
异步上下文管理器
| 方法 | 说明 | 
|---|---|
__aenter__(self) | 
在语义上类似于 __enter__(),仅有的区别是它必须返回一个 可等待对象 | 
__aexit__(self) | 
在语义上类似于 __exit__(),仅有的区别是它必须返回一个 可等待对象 | 
00. 漏网之鱼
| 方法 | 说明 | 
|---|---|
__objclass__  | 
会被 inspect 模块解读为指定此对象定义所在的类 | 
__slots__ | 
允许我们显式地声明数据成员(如特征属性)并禁止创建 dict 和 weakref | 
__mro_entries__ | 
|
__prepare__ | 
|
__class__ | 
|
__classcell__ | 
说在最后
码农高天出了一个系列讲解魔术方法,推荐观看https://www.bilibili.com/video/BV1b84y1e7hG
流畅的python对魔术方法的讲解比较深入,贯穿全文,有一定难度,基础薄弱的谨慎
前面在哪里说过很多内置函数、操作、运算符的背后多数都是这些魔术方法的实现。
- with上下文管理器的背后是
__enter__(self)和__exit__(self, exc_type, exc_value, traceback) - 多数的运算符背后都是的10. 模式数字类型
 - 内置函数如len的背后是
__len__ 
- with上下文管理器的背后是
 
漫谈Python魔术方法,见过的没见过的都在这里了的更多相关文章
- python魔术方法
		
在类中有一些特殊的方法具有特殊的意义,比如__init__和__del__方法,它们的重要性我们已经学习过了. 一般说来,特殊的方法都被用来模仿某个行为.例如,如果你想要为你的类使用x[key]这样的 ...
 - Python 魔术方法笔记
		
魔术方法总是被__包围, 如__init__ , __len__都是常见的魔术方法,这里主要写一下我遇到的一些魔术方法 setitem 对某个索引值赋值时 即可以进行赋值操作,如 def __seti ...
 - 记一次 Apache HUE 优化之因使用 Python 魔术方法而遇到的坑
		
最近的工作是基于 Apache HUE 做二次开发.刚接手 HUE 的代码的时候,内心是崩溃的:开源的代码,风格很多种, 代码比较杂乱; 虽是基于 Django 开发的,但是项目的结构改变很大; 很多 ...
 - Python 魔术方法指南
		
入门 构造和初始化 构造定制类 用于比较的魔术方法 用于数值处理的魔术方法 表现你的类 控制属性访问 创建定制序列 反射 可以调用的对象 会话管理器 创建描述器对象 持久化对象 总结 附录 介绍 此教 ...
 - Python魔术方法-Magic Method
		
介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...
 - python魔术方法总结
		
获取属性 __ getattr __(self, name) 定义当用户试图获取一个不存在的属性时的行为 __ getattribute __(self, name) 定义当该类的属性被访问时的行为 ...
 - 032.Python魔术方法__new__和单态模式
		
一 __new__ 魔术方法 1.1 介绍 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值 ...
 - [python]魔术方法
		
一.初始化: 1.__new__方法,初始化过程中第一个用到的方法(用处不大). 2.之后,__init__方法,构造方法. 3.最后,在对象回收时,调用__del__方法.如果解释器退出时,对象还存 ...
 - Python 魔术方法及调用方式
		
魔术方法 调用方式 解释 __new__(cls [,...]) instance = MyClass(arg1, arg2) __new__ 在创建实例的时候被调用 __init__(self [, ...
 - jmeter 调用python的方法三种 (还没试)
		
参考文章1: Jmeter 运行 Python 代码进行 AK/SK 认证 (使用 OS Process Sampler) 思路是:jmeter调用shell,用shell执行py 参考文章2: Jm ...
 
随机推荐
- Python通过解压ofd文件获取发票信息
			
实际上ofd.docx.xlsx等文件就是一个压缩文件,是可以被解压处理的.所以我们把一个ofd格式的发票文件解压后就可以看到它的目录,如下: 再用谷歌或者IE打开里面的xml属性的文件,就可以看到发 ...
 - python  实现两个多维数组去重处理
			
a = [[1,2,3,4],[5,6,7,8],[11,12,13,14],[23,24,12,11]] b = [[5,6,7,8],[23,24,12,11]] c = [] for i in ...
 - 错题记录:C51同一个hex文件偶尔效果不行 的处理方法
			
51单片机很多方面和C语言有区别,经验下来,总结以下:1.关于变量报错:报错的原因大多是因为编译器C++版本不同,所以变量我都推荐使用驼峰命名法;2.如果同一个hex文件,或者改的代码自己认为没问题 ...
 - 使用vite创建vue3+ts项目完整流程
			
1.创建项目 npm init vite@latest 依次输入项目名称.选择vue.选择ts 2.引入依赖 cd 项目名称 npm install 3.启动项目 npm run dev 4.引入vu ...
 - docker部署服务器
			
Docker部署PostGres docker run -d --name postgres --restart always -e POSTGRES_USER='postgres' -e POSTG ...
 - SQL相关知识
			
SQL(Structure Query Language) 结构化查询语言,它是关系型数据库的应用语言,由IBM上世纪70年代开发出来的. SQL语言规范 语句以;封号结束 ...
 - 通过cmd对数据库SQL进行创建表空间并创建用户
			
通过cmd对数据库SQL进行创建表空间并创建用户 1.创建表空间:create tablespace stx(名字) datafile ' 目录路径\stx(名字).dbf ' size 64m; 2 ...
 - react和vue的区别及优缺点
			
区别: vue是双向绑定的,采用template: react是单向的,采用jsx. Vue的优缺点: 简单.快速.强大.对模块友好,但不支持IE8. React的优缺点: 速度快.跨浏览器兼容.模块 ...
 - windows ftp 简单搭建, wget ftp
			
事情起因: 公司客户一台数据库服务器突然连不上了,一开始以为是密码过期了,联系学校的老师给改了密码之后,还是连不上,然后就怀疑是不是ssh服务有问题.然后发现这台服务器上没有安装包,yum 命令也不好 ...
 - python代码抛出异常
			
from traceback import format_exc except Exception: print(format_exc())