第一章 Python数据模型
不管在哪种框架下写程序,都会花费大量时间去实现那些会被框架本身调用的方法, Python也不例外,Python解释器碰到特殊的句法时,会使用特殊方法去激活一些基本的对象操作,这些特殊方法的名字以两个下划线开头,以两个下划线结尾(例如__getitem__)。
这些特殊方法名能让你自己的对象实现和支持以下的语言构架,并与之交互:
• 迭代
• 集合类
• 属性访问
• 运算符重载
• 函数和方法的调用
• 对象的创建和销毁
• 字符串表示形式和格式化
• 管理上下文(即with块)
1.使用特殊方法
在很多时候,特殊方法的调用是隐式的,比如for i in x:这个语句,背后其实用的是iter(x),而这个函数的背后则是x.iter()方法。当然前提是这个方法在x中被实现了。
如下程序实现:
一个二维向量加法的例子,Vector(2,4) + Vextor(2,1) = Vector(4,5)
__add__实现了+操作符的重写
from math import hypot
class Vector:
def __init__(self,x=0,y=0):
self.x = x
self.y = y
def __repr__(self):
return 'Vector(%r,%r)' %(self.x,self.y)
def __abs__(self):
return hypot(self.x,self.y)
def __bool__(self):
return bool(abs(self))
def __add__(self,other):
print "runing...."
x = self.x+other.x
y = self.y+other.y
return Vector(x,y)
def __mul__(self,scalar):
return Vector(self.x *scalar,self.y*scalar)
运行结果:
|>>a = Vector(2,4)
|>>b = Vector(2,1)
|>>c= a+b
runing…
| >>c
Vector(4,5)
当执行+操作时,解释器自动调用__add__方法
2.特殊方法一览
类别 | 方法 |
---|---|
字符串/ 字节序列表示形式 | __repr__、__str__、__format__、__bytes__ |
数值转换 | __abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__ |
集合模拟 | __len__、__getitem__、__setitem__、__delitem__、__contains__ |
迭代枚举 | __iter__、__reversed__、__next__ |
可调用模拟 | __call__ |
上下文管理 | __enter__、__exit__ |
实例创建和销毁 | __new__、__init__、__del__ |
属性管理 | __getattr__、__getattribute__、__setattr__、__delattr__、__dir__ |
属性描述符 | __get__、__set__、__delete__ |
跟类相关的服务 | __prepare__、__instancecheck__、__subclasscheck__ |
表1-2:跟运算符相关的特殊方法
类别 | 方法 |
---|---|
一元运算符 | __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__ |、__xor__ ^ |
反向位运算符 | __rlshift__、__rrshift__、__rand__、__rxor__、__ror__ |
增量赋值位运算符 | __ilshift__、__irshift__、__iand__、__ixor__、__ior__ |
小结:
通过实现特殊方法,自定义数据类型可以表现得跟内置类型一样,从而让我们写出更具表达力的代码——或者说,更具Python风格的代码。
Python对象的一个基本要求就是它得有合理的字符串表示形式,我们可以通过__repr__和__str__来满足这个要求。前者方便我们调试和记录日志,后者则是给终端用户看的。这就是数据模型中存在特殊方法__repr__和__str__的原因。