《流畅的python》读书笔记(2)

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__,当我们在控制台里打印一个向量的实例时,
    # 得到的字符串可能会是 
    # 在老的使用% 符号的字符串格式中,这个函数返回的结果用来代替 %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 来满足这个要求。前者方便我们调试和记录日志,后者则是给终端用户看的。这就是数据模型中存在特殊方法 reprstr 的原因
对序列数据类型的模拟是特殊方法用得最多的地方

你可能感兴趣的:(读书笔记,Python)