1.2 如何使用特殊方法
什么是特殊方法?
特殊方法的存在是为了被python解释器调用的 而非程序员调用的
书中提到了CPython 什么是CPython?
Cpython是指C语言实现的python,python还有其他的实现的版本
当我们从Python官方网站下载并安装好Python后,我们就直接获得了一个官方版本的解释器:CPython。
这个解释器是用C语言开发的,所以叫CPython。在命令行下运行python就是启动CPython解释器。
CPython是使用最广的Python解释器
书中提到了PyVarObject 什么是 PyVarObject?
首先得了解PyObject
PyObject 对应着C语言层面的一个结构,说白了就是一个基本的对象保存了每个对象必有的东西
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject ob_type;
} PyObject;
其次开始说明PyVarObject
PyVarObject 是一个变长对象如List String 与PyObject相比只是多了一个ob_size属性,指明变长对象中有多少个元素。
typedef struct {
PyObject ob_base; // PyObject头
Py_ssize_t ob_size; / Number of items in variable part */
Py_ssize_t可以认为是整型
} PyVarObject;
书中的一段代码
# 一个简单的二维向量类
from math import hypot
class Vector:
def __init__(self, x=0, y=0):
self.x = x;
self.y = y;
# repr,它能把一个对象用字符串的形式表达出来以便辨认,
# 这就是“字符串表示形式”。repr 就是通过 __repr__ 这个特殊方法来得到一个对象的字
# 符串表示形式的。类似Java中的toString()
# 如果没有实现 __repr__,当我们在控制台里打印一个向量的实例时,
# 得到的字符串可能会是 <Vector object at 0x10e100070>。
# 在老的使用% 符号的字符串格式中,这个函数返回的结果用来代替 %r 所代表的对象
# 用到了 %r 来获取对象各个属性的标准字符串表示形式
# __repr__ 和 __str__ 的区别在于,后者是在 str() 函数被使用,或是在用 print 函数
# 打印一个对象的时候才被调用的,并且它返回的字符串对终端用户更友好
# 如果你只想实现这两个特殊方法中的一个,__repr__ 是更好的选择,因为如果一个对象
# 没有 __str__ 函数,而 Python 又需要调用它的时候,解释器会用 __repr__ 作为替代
def __repr__(self):
return 'Vector(%r,%r)' % (self.x, self.y)
def __abs__(self):
# hypot返回欧几里得距离 sqrt(x*x + y*y)
return hypot(self.x, self.y)
# 自定义的布尔值
# 尽管 Python 里有 bool 类型,但实际上任何对象都可以用于需要布尔值的上下文中(比如
# if 或 while 语句,或者 and、or 和 not 运算符)。为了判定一个值 x 为真还是为假,
# Python 会调用 bool(x),这个函数只能返回 True 或者 False。
# 如果向量的模是0 返回False 否则返回True
def __bool__(self):
# return bool(abs(self))
# 更易读的方式,当且仅当x 与 y都为0的 时候向量为0
return bool(self.x or self.y)
# 返回值是新创建的向量对象,被操作的对象是原封不动的
def __add__(self, other):
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)
if __name__ == '__main__':
v1 = Vector(2, 4)
v2 = Vector(2, 1)
# 两向量相加
print(v1 + v2) # Vector(4,5)
v = Vector(3, 4)
# 向量的模
print(abs(v)) # 5.0
# 向量的数乘
print(v * 3)
# 向量先数乘 后求模
print(abs(v * 3))
书中小结
通过实现特殊方法,自定义数据类型可以表现得跟内置类型一样,从而让我们写出更具表
达力的代码——或者说,更具 Python 风格的代码。
Python 对象的一个基本要求就是它得有合理的字符串表示形式,我们可以通过 __repr__和 str 来满足这个要求。前者方便我们调试和记录日志,后者则是给终端用户看的。这就是数据模型中存在特殊方法 repr 和 str 的原因
对序列数据类型的模拟是特殊方法用得最多的地方