什么是魔术方法? 在Python中,所有以双下划线__
包起来的方法,统称为Magic Method(魔术方法) ,它是一种的特殊方法,普通方法需要调用,而魔术方法不需要调用就可以自动执行。或许在之前,你不知道这个概念,但我保证,只要你用过Python,那你一定在不经意间用过魔术方法。例如:对于两个字符串,你可能会用“+”号把他们连起来,得到一个合起来之后的字符串:
1 2 3 4 5 6 7 a = 'Hello, ' b = 'World!' c = a + b print (c)>>> Hello, World!
但是,按理说,“+”只能对于数使用,字符串之间是不能相加的,那为什么上面那段程序还能够运行呢?这就是魔术方法的功劳了。事实上,因为str类实现了__add__魔术方法,进而实现了运算符重载,所以我们可以通过“+”来实现字符串的拼接。
魔术方法在类或对象的某些事件触发后会自动执行,让类具有神奇的“魔力”。如果希望根据自己的程序定制自己特殊功能的类,那么就需要对这些方法进行重写。例如,如果我们想要实现一个自己的字符串类,在两个长度相等的全是字母的字符串相加时,返回一个结果字符串,它的每个字符是两个字符串相应位置字母表排序更大的那个字母,那么我们就可以重写__add__魔术方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Mystr (str ): def __init__ (self, s ): self.s = s def __add__ (self, other ): res = [] if len (self.s) != len (other): raise ValueError else : for i in range (len (self.s)): if self.s[i] > other[i]: res.append(self.s[i]) else : res.append(other[i]) return '' .join(res) a = Mystr('jasndkcaww' ) b = Mystr('lopergvmei' ) print (a + b)>>> losnrkvmww
常用的魔术方法 1. 初始化方法____init____ 1 2 3 4 触发机制:实例化对象之后立即触发 参数:至少有一个self,接收当前对象,其他参数根据需要进行定义 返回值:无 作用:初始化对象的成员
2. 获取对象长度__len__ 1 2 3 4 5 触发时机:使用len(对象) 的时候触发 参数:一个参数self 返回值:必须是一个整型 作用:可以设置为检测对象成员个数,但是也可以进行其他任意操作 注意:返回值必须必须是整数,否则语法报错,另外该要求是格式要求。
3. 构造对象的字符串表示__str__与__repr__ 1 2 3 4 5 触发时机:__str__:使用print(对象)或者str(对象),__repr__:repr(对象)的时候触发 参数:一个self接收对象 返回值:必须是字符串类型 作用:print(对象时)进行操作,得到字符串,通常用于快捷操作 注意:__repr__更严谨,是主要给机器用的格式,而__str__主要是给用户看的格式
未完待续……
魔术方法大全
方法名
参数列表
调用时机
返回值类型
备注
__repr__
self
当调用repr()
函数时
str
返回值应为重建该对象的Python表达式(如果可能),或包含其他信息的字符串<...>
__str__
self
当调用str()
函数时
str
调用print()
等其他函数时会隐式调用__str__()
,当不存在__str__()
时会自动调用__repr__()
__format__
self, format_spec
当调用format()
函数时
str
object.__format__(x, '')
等价于str(x)
__bytes__
self
当调用bytes()
函数时
bytes
返回值是对象的字节表示
__bool__
self
调用bool()
函数时
bool
当__bool__
函数没有定义时,会隐式 调用__len__
,如果__len__
也没有 定义,则返回True
__complex__
self
调用commplex()
函数时
complex
__int__
self
调用int()
函数时
int
__float__
self
调用float()
函数时
float
__hash__
self
调用hash()
函数时
hash()
函数将__hash__()
的返回值 截断到Py_ssize_t
的范围内,64位系 统下Py_ssize_t
为8字节;set
等类 型的操作也会调用对象的__hash__
函 数
__index__
self
调用operator.index()
或Python需要整数值时
int
当__int__
、__float__
、 __complex__
没有实现时,这些函数隐式地调用__index__
__len__
self
调用len()
函数时
int
返回值必须为非负整数,在CPython中返回值不能超过sys.maxsize
中定义的值,否则len()
等函数会抛出OverflowError
等异常
__getitemm__
self, key
使用[]
运算符时(右值)
key
可以为合法的数组下标,也可以是反向的下标,也可以是序列的切片,该函数应在key
类型不对应时抛出TypeError
,key
超出范围时抛出IndexError
或KeyError
(对于映射类型)
__setitem__
self, key, value
使用[]
运算符时(左值)
None
key
参数的取值及异常处理与__getitem__
函数相同
__delitem__
self, key
使用del
删除序列中的元素时
None
对于不可删除的序列或映射,无需实现该函数,其他同__getitem__
__contains__
self, item
使用in
作为运算符时
bool
对于映射类型,__contains__
接收的item
参数对应映射的key
部分而不是value
部分。若没有定义该函数,Python首先通过__iter__
进行查找,其次使用__getitem__
进行查找
__iter__
self
调用iter()
函数或使用循环时
返回值应为可迭代对象,对于可迭代对象,__iter__
函数返回自身
__reversed__
self
调用reversed()
函数时
返回值应为可迭代对象,且是原序列的逆序
__next__
self
调用next()
函数时
返回可迭代对象中的下一个元素,当到达最后一个元素时抛出StopIteration
__call__
self, *args, **kwargs
当对象以函数的方式被调用时
定义了__call__
方法的对象属于typing.Callable
类型
__enter__
self
使用with
关键词声明上下文时
Any
返回值分配给as
关键词指明的对象
__exit__
self, exc_type, exc_value, traceback
离开with
块时
Any
若with
块执行过程中没有出现异常,则exc_type, exc_value, traceback
参数均为None
,否则exit
块可以对异常进行处理
__new__
cls[, ...]
创建类实例时
Any
__new__
为静态方法且先于__init__
执行,__new__
的其余参数会传递给__init__
。若__new__
返回的类型与创建的类型不对应,则不会执行__init__
__init__
self, ...
初始化类实例时
None
若基类定义了__init__
,则在子类的__init__
中必须有super().__init()
的显式调用
__del__
self
对象销毁时
None
当对象的引用计数减为0时,对象才可能被删除
__getattribute__
self, name
使用self.name
访问对象的属性时
Any
为避免无限递归,子类的__getattribute__
方法的实现中必须包含父类的__getattribute__
方法调用
__getattr__
self, name
使用self.name
访问对象的不存在属性或__getattribute__
函数抛出AttributeError
异常
Any
当__getattribute__
正常执行时__getattr__
不会执行
__setattr__
self, name, value
使用self.name
设置属性的值时
None
当试图通过__setattr__
向对象设置属性值时必须通过类型的__setattr__
方法进行设置
__delattr__
self, name
执行del self.name
时
None
仅当del self.name
语句有意义时,才需要实现该方法
__dir__
self
执行dir()
函数时
Sequence
dir()
会自动进行排序处理
运算符重载相关的魔术方法:
描述
方法名
运算符
取负
__neg__
-
取正
__pos__
+
绝对值
__abs__
abs()
小于
__lt__
<
小于等于
__le__
<=
等于
__eq__
==
不等于
__ne__
!=
大于
__gt__
>
大于等于
__ge__
>=
相加
__add__
+
相减
__sub__
-
相乘
__mul__
*
实数除
__truediv__
/
整数除
__floordiv__
//
取余
__mod__
%
整数除+取余
__divmod__
divmod()
乘方
__pow__
**
取整
__round__
round()
按位取反
__invert__
~
左移
__lshift__
<<
右移
__rshift__
>>
按位与
__and__
&
按位或
__or__
`
按位异或
__xor__
^