#89 Python 源码学习 04: int

2021-07-20

经过源码分析,可以得知,所有类型的定义都是通过 object.c 中的 INIT_TYPE 语句,比如 INIT_TYPE(&PyLong_Type, "int");

然后,可能是通过 SETBUILTIN("int", &PyLong_Type); 设置成内置方法。

int 类型最后就指向了一个叫做 PyLong_TypePyTypeObject 类型变量。

PyTypeObject

Objects/longobject.c

PyTypeObject PyLong_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "int",                                      /* tp_name */
    offsetof(PyLongObject, ob_digit),           /* tp_basicsize */
    sizeof(digit),                              /* tp_itemsize */
    0,                                          /* tp_dealloc */
    0,                                          /* tp_vectorcall_offset */
    0,                                          /* tp_getattr */
    0,                                          /* tp_setattr */
    0,                                          /* tp_as_async */
    long_to_decimal_string,                     /* tp_repr */
    &long_as_number,                            /* tp_as_number */
    0,                                          /* tp_as_sequence */
    0,                                          /* tp_as_mapping */
    (hashfunc)long_hash,                        /* tp_hash */
    0,                                          /* tp_call */
    0,                                          /* tp_str */
    PyObject_GenericGetAttr,                    /* tp_getattro */
    0,                                          /* tp_setattro */
    0,                                          /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
        Py_TPFLAGS_LONG_SUBCLASS,               /* tp_flags */
    long_doc,                                   /* tp_doc */
    0,                                          /* tp_traverse */
    0,                                          /* tp_clear */
    long_richcompare,                           /* tp_richcompare */
    0,                                          /* tp_weaklistoffset */
    0,                                          /* tp_iter */
    0,                                          /* tp_iternext */
    long_methods,                               /* tp_methods */
    0,                                          /* tp_members */
    long_getset,                                /* tp_getset */
    0,                                          /* tp_base */
    0,                                          /* tp_dict */
    0,                                          /* tp_descr_get */
    0,                                          /* tp_descr_set */
    0,                                          /* tp_dictoffset */
    0,                                          /* tp_init */
    0,                                          /* tp_alloc */
    long_new,                                   /* tp_new */
    PyObject_Del,                               /* tp_free */
};

其中所有的方法就在 PyMethodDef long_methodsPyNumberMethods long_as_number 中。
尤其是 long_as_number 可能就是那些重载操作符的基础。

long_newlong_new_impl

可能是 int 方法对应的实现。

#86 Python 解释器

2021-06-21

除了 CPython 之外的几种比较知名的 Python 实现:

  1. PyPy
  2. Jython 原名 JPython,原作者停止维护之后,社区将项目改名并继续维护。
  3. IronPython 运行在 .NET 平台
    之前由微软开发(姊妹项目 IronRuby),后来放弃。项目由志愿者维护。
  4. Pyston Dropbox 停止资助该项目,不过还活着,在继续发版。
  5. Unladen Swallow 谷歌的项目,看介绍,思路和 Pyston 差不多(在 pyston 前面),早死翘翘了
  6. Stackless Python: greenlet 就是从这个项目中弄出来的一个成果。
  7. MicroPython: 专门运行在单片机上(有一个 fork 叫 CircuitPython,似乎也有点名气)

#85 常见的 Python 性能提升手段

2021-06-21

Python 本身的性能现在还很有待提升,但是为什么没有阻碍它的推广呢?

因为 Python 常常被当作是一种胶水语言,它有很好的与 C 互操作性,一直维护与 C 库对接的 API,也就是说很容易可以通过 C 拓展来提升性能。

新的运行时

  • PyPy 据说能有很大提升
  • Pyston LLVM 编译器架构 + JIT
    https://github.com/pyston/pyston
    注意:Dropbox 放弃了这个项目,转向 Go 语言,但这个项目还在继续开发中, 比较活跃
  • Psyco http://psyco.sourceforge.net/ 已经没有维护了,据说只维护到 Python 2.4
    官方推荐 PyPy

局部优化

C/C++ 绑定

  • SWIG: C/C++ 写的代码自动绑定到 Python,就是说生成一个 Python 可以调用的 .so 模块
  • pybind11
  • Boost.Python

直接调用 C

直接开发 CPython 拓展模块(include <Python.h>)也可以,但我不觉得这是一个好办法。

GPU

  • GPULib
  • PyStream
  • PyCUDA
  • PyOpenCL

其他

  • F2PY: Fortran to Python, 将 Fortran 代码自动绑定到 Python, NumPy 的一部分
    也是编译成 .so 包
    我不清楚相关应用场景,以及这个方案是否有性能上的优势

参考资料与拓展阅读

#82 Python 源码学习 02: PyObject

2021-06-19

源码

Include/object.h

/* Nothing is actually declared to be a PyObject, but every pointer to
 * a Python object can be cast to a PyObject*.  This is inheritance built
 * by hand.  Similarly every pointer to a variable-size Python object can,
 * in addition, be cast to PyVarObject*.
 */
typedef struct _object {
    _PyObject_HEAD_EXTRA   // 如果开启了 Py_TRACE_REFS 增加一个 _ob_next, _ob_prev
                           // 使 all live heap objects 组成一个双向链表
    Py_ssize_t ob_refcnt;  // 长整型
    PyTypeObject *ob_type;
} PyObject;

/* Cast argument to PyObject* type. */
#define _PyObject_CAST(op) ((PyObject*)(op))
#define _PyObject_CAST_CONST(op) ((const PyObject*)(op))

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;

/* Cast argument to PyVarObject* type. */
#define _PyVarObject_CAST(op) ((PyVarObject*)(op))

#define Py_REFCNT(ob)           (_PyObject_CAST(ob)->ob_refcnt)
#define Py_TYPE(ob)             (_PyObject_CAST(ob)->ob_type)
#define Py_SIZE(ob)             (_PyVarObject_CAST(ob)->ob_size)

PyObject

相当于所有 Python 对象的父类,包含类型,引用计数等信息。

注释说的很清楚,不会有直接声明的 PyObject 变量,只会有 PyObject* 指针,所有指向 Python 对象的指针都可以转换成 PyObject*

PyVarObject

表示 ob_size 个 PyObject,也就是说 PyVarObject 是一个 PyObject 的容器。

#81 NumPy 基础

2021-06-18

NumPy 提供了一个高效的数据结构(数组/矩阵)及对应运算支持,据说效率和 C 接近,是 Python 科学计算生态的基础。