第零章 学前准备
第一章 数据结构 – 基本数据类型
第一章 数据结构 – 字符串
第一章 数据结构 – 列表、元组和切片
第一章 数据结构 – 字典
第一章 数据结构 – 集合
第一章 – 数组、队列、枚举
第一章 数据结构 – 序列分类
第二章 控制流程
第三章 函数也是对象 – 函数定义以及参数
第三章 函数也是对象 – 高阶函数以及装饰器
第三章 函数也是对象 – lambda 表达式、可调用函数及内置函数
第四章 面向对象编程 – 自定义类、属性、方法和函数
第四章 面向对象编程–魔术方法1
文章目录
第四章 面向对象编程 – 魔术方法1
4.4 特殊方法(magic method)
一个类可以定义一些特殊命名的方法,它们使用特殊语法调用,比如算术运算符、下标以及切片。魔术方法(magic method)是特殊方法的昵称。
4.4.1 特殊方法一览
更多可参考DataModel
类别 | 方法名 |
---|---|
字符串/字节序列表示形式 | __repr__ 、 __str__ 、 __format__(格式化字符串str.format) 、 __bytes__ |
数值转换 | __abs__ 、 __bool__ 、 __complex__ 、 __int__ 、 __float__ 、 __hash__ 、 __index__ |
集合模拟 | __len__ 、 __length_hint__ 、 __getitem__ 、 __setitem__ 、 __delitem__ 、 __missing__ 、 __contains__ |
迭代枚举 | __iter__ 、 __reverse__ 、 __next__ |
可调用模拟 | __call__ |
上下文管理 | __enter__ 、 __exit__ |
实例创建和销毁 | __new__ 、 __init__ 、 __del__ |
属性管理 | __getattr__ 、 __getattribute__ 、 __setattr__ 、 __delattr__ 、 __dir__ |
属性描述符 | __get__ 、 __set__ 、 __delete__ |
跟类相关的服务 | __prepare__ 、 __instancecheck__ 、 __subclasscheck__ |
类别 | 方法名 |
---|---|
一元运算符 | __neg__ - 、 __pos__ + 、 __abs__ abs() |
众多比较运算符 | __lt__ < 、 __le__ <= 、 __eq__ == 、 __ne__ != 、 __gt__ > 、 __ge__ >= |
算术运算符 | __add__ + 、 __sub__ - 、 __mul__ * 、 __truediv__ / 、 __floordiv__ // 、 __mod__ % 、 __divmod__ divmod 、 __pow__ **或pow() 、 __round round() |
反向算术运算符 | __radd__ 、 __rsub__ 、 __rmul__ 、 __rtruediv__ 、 __rfloordiv__ 、 __rmod__ 、 __rdivmod__ 、 __rpow__ |
增量赋值算术运算符 | __iadd__ 、 __isub__ 、 __imul__ 、 __itruediv__ 、 __ifloordiv__ 、 __imod__ 、 __ipow__ |
位运算符 | __invert__ - 、 __lshift__ << 、 __rshift__ >> 、 __and__ & 、 __or__ |
反向位运算符 | __rlshift__ 、 __rrshift__ 、 __rand__ 、 __ror__ 、 __rxor__ |
增量赋值位运算符 | __ilshift__ 、 __irshift__ 、 __iand__ 、 __ior__ 、 __ixor__ |
4.4.2 重要特殊方法调用
4.4.2.1 实例创建和销毁
object.__new__(cls[, ...])
new
方法在调用后可以产生类cls
的实例。并且,new
是静态方法,第一个参数必须是需要创建实例的cls
为第一个参数,该参数在实例化时由解释器自动提供。new的典型实现应该通过super().__new__(cls[, ...])
调用父类的__new__
方法先创建cls
的实例,在将实例返回之前可以做一些想要的修改,以达到自己的目标。
如果__new__
被调用并返回cls
的实例,那么__init__
方法将会被调用。然而,如果__new__
没有返回实例,__init__
方法不会调用。__new__
可以让我们在继承不可变类型(比如int
,str
和tuple
)创建实例时实现一些自定义操作。object.__init__(self[, ...])
init
方法在实例被创建之后调用。如果一个基类有init
方法,那么在子类的init
方法中,必须显示地调用基类的init
方法(比如:super().__init__([args...])
),这样才能保证实例中基类部分被初始化,实例被完整地实现。一般来说,new
创建实例,init
自定义实例。如果一个non-None
值在init
被返回,那么在运行时,将会抛出TypeError
异常。object.__del__(self)
当一个对象要被销毁时,这时解释器就会调用对象的__del__
对象。一般,程序员很少主动调用__del__
去销毁对象,而是系统自动调用。__del__
与内置函数del
不同,del
只是删除一个对象的引用,而__del__
是当引用的数量为零时才会被调用。
# 使用__new__实现单例类
class Singleton:
__instance = None
def __new__(cls):
if cls.__instance is None:
cls.__instance = super().__new__(cls)
return cls.__instance
s_1 = Singleton()
s_2 = Singleton()
print(s_1 is s_2)
4.4.2.2 类相关的服务
class.__instancecheck__(self, instance)
:如果instance
应被视为class
的一个(直接或间接)实例则返回真值。如果定义了此方法,则会被调用以实现isinstance(instance, class)
。class.__subclasscheck__(self, subclass)
:Return true
如果subclass
应被视为class
的一个(直接或间接)子类则返回真值。如果定义了此方法,则会被调用以实现issubclass(subclass, class)
。__prepare__
4.4.2.2 字符串/字节序列表示形式
object.__repr__(self)
:调用内置函数repr
时被调用,返回一个对象的字符串表达形式,即返回该对象的描述。如果没有实现,得到的字符串将会是"xxx object at 0x102100070"
的形式。交互式控制台和调试程序(debugger
)用repr
函数来获取字符串表示形式,所以返回的字符串应该准确", "无歧义,并且尽可能表达出如何用代码创建出这个被打印的对象。object.__str__(self)
:内置函数str
时调用吗,与__repr__
不同,__str__
返回的字符串将会是更易于阅读的,并且,如果定义了rep而没有定义__str__,那么会用__repr__
代替__str__
。总之,尽量实现__repr__
,如果你觉得__repr__
不够易懂,那么可以再实现__str__
,实现一个更易于阅读的版本。object.__bytes__(self)
:Called by bytes to compute a byte-string representation of an object. This should return a bytes object.object.__format__(self, format_spec)
:调用内置的format
和str.format()
方法时,调用,返回对象的格式化字符串表达式。参数format_spec
是对格式化选项的描述,比如:%s", "%r等。
4.4.2.3 数值转换
object.__hash__(self)
:通过内置函数hash()
以及像set
", “frozenset
”, "dict
散列容器中对成员的操作时调用。__hash__
返回值应该是一个整数。比较推荐的一种实现是把对象内部所有的属性放进一个元组,然后返回该元组的哈希值。
If a class does not define an__eq__()
method it should not define a__hash__()
operation either; if it defines__eq__()
but not__hash__()
, its instances will not be usable as items in hashable collections. If a class defines mutable objects and implements an__eq__()
method, it should not implement__hash__()
, since the implementation of hashable collections requires that a key’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).
User-defined classes have__eq__()
and__hash__()
methods by default. 这时,默认的__eq__
也是使用is
判断是否相等。
A class that overrides__eq__()
and does not define__hash__()
will have its__hash__()
implicitly set to None. When the__hash__()
method of a class is None, instances of the class will raise an appropriate TypeError when a program attempts to retrieve their hash value, and will also be correctly identified as unhashable when checking isinstance(obj, collections.abc. Hashable).
If a class that does not override__eq__()
wishes to suppress hash support, it should include__hash__ = None
in the class definition.object.__bool__(self)
:Called to implement truth value testing and the built-in operationbool()
; should return False or True. When this method is not defined,__len__()
is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither__len__()
nor__bool__()
, all its instances are considered true.object.__complex__(self)
、object.__int__(self)
、object.__float__(self)
、object.__abs__(self)
:Called to implement the built-in functions complex(), int(), float() and abs(). Should return a value of the appropriate type.object.__index__(self)
:Called to implementoperator.index()
, and whenever Python needs to losslessly convert the numeric object to an integer object (such as in slicing, or in the built-in bin(), hex() and oct() functions). Presence of this method indicates that the numeric object is an integer type. Must return an integer.
If__int__()
,__float__()
and__complex__()
are not defined then corresponding built-in functionsint()
,float()
andcomplex()
fall back to__index__()
.
PEP 357 – Allowing Any Object to be Used for Slicing