Python 解释器实现:对象行为
目录

之前的文章Python 解释器实现:内置数据类型分析了Python的内置数据类型。从面向对象的角度来看,这些数据类型是对象的数据成员,而本文将分析这些数据类型对应的方法成员。Python解释器用这种方式实现了面向对象的设计方法。

Py*_Type

每个内置Object类型都有对应的Type对象:

  • PyNoneObject -> PyNone_Type
  • PyBoolObject -> PyBool_Type
  • PyIntObject -> PyInt_Type
  • PyLongObject -> PyLong_Type
  • PyFloatObject -> PyFloat_Type
  • PyComplexObject -> PyComplex_Type
  • PyStringObject -> PyString_Type
  • PyUnicodeObject -> PyUnicode_Type
  • PyListObject -> PyList_Type
  • PyTupleObject -> PyTuple_Type
  • PyDictObject -> PyDict_Type
  • PySetObject -> PySet_Type

每个Type对象都包含很多函数指针,这些函数就是对应Object类型需要支持的操作。 Type对象是PyTypeObject类型的实例化,PyTypeObject定义了所有函数的全集:

// Include/object.h
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */  // __name__
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */  // __basicsize__ __itemsize__

/* Methods to implement standard operations */

destructor tp_dealloc;      //
printfunc tp_print;         // __str__?
getattrfunc tp_getattr;     // __getattr__
setattrfunc tp_setattr;     // __setattr__
cmpfunc tp_compare;         // __eq__ __ne__ __lt__ __gt__ __le__ __ge__
reprfunc tp_repr;           // __repr__

/* Method suites for standard classes */

PyNumberMethods *tp_as_number;  // __add__/__iadd__ ... ___nonzero__ ... __lshift__ ... __and__ ... __hex__ ... __index__
PySequenceMethods *tp_as_sequence; // __len__ __contains__ ...
PyMappingMethods *tp_as_mapping;   // __len__ ...

/* More standard operations (here for binary compatibility) */

hashfunc tp_hash;            // __hash__
ternaryfunc tp_call;         // __call__
reprfunc tp_str;             // __format__?
getattrofunc tp_getattro;    // __getattribute__
setattrofunc tp_setattro;    // __setattribute__

/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;

/* Flags to define presence of optional/expanded features */
long tp_flags;

const char *tp_doc; /* Documentation string */    // __doc__

/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;

/* delete references to contained objects */
inquiry tp_clear;

/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;

/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;

/* Added in release 2.2 */
/* Iterators */
getiterfunc tp_iter;                 // __iter__
iternextfunc tp_iternext;

/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;                   // __dict__?
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
Py_ssize_t tp_dictoffset;
initproc tp_init;                    // __init__
allocfunc tp_alloc;
newfunc tp_new;                      // __new__
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
destructor tp_del;                   // __del__

/* Type attribute cache version tag. Added in version 2.6 */
unsigned int tp_version_tag;
} PyTypeObject;

从面相对象角度,PyTypeObject是一个接口,Type对象实现了这个接口(非全部)。 Type对象大写看起来是C的类型定义,其实是PyTypeObject的实例对象。 如PyInt_Type对象:

PyTypeObject PyInt_Type = {
PyVarObject_HEAD_INIT(&amp;PyType_Type, 0)
"int",
sizeof(PyIntObject),
0,
(destructor)int_dealloc,                    /* tp_dealloc */
(printfunc)int_print,                       /* tp_print */
0,                                          /* tp_getattr */
0,                                          /* tp_setattr */
(cmpfunc)int_compare,                       /* tp_compare */
(reprfunc)int_to_decimal_string,            /* tp_repr */
&amp;int_as_number,                             /* tp_as_number */
0,                                          /* tp_as_sequence */
0,                                          /* tp_as_mapping */
(hashfunc)int_hash,                         /* tp_hash */
0,                                          /* tp_call */
(reprfunc)int_to_decimal_string,            /* tp_str */
PyObject_GenericGetAttr,                    /* tp_getattro */
0,                                          /* tp_setattro */
0,                                          /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE | Py_TPFLAGS_INT_SUBCLASS,          /* tp_flags */
int_doc,                                    /* tp_doc */
0,                                          /* tp_traverse */
0,                                          /* tp_clear */
0,                                          /* tp_richcompare */
0,                                          /* tp_weaklistoffset */
0,                                          /* tp_iter */
0,                                          /* tp_iternext */
int_methods,                                /* tp_methods */
0,                                          /* tp_members */
int_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 */
int_new,                                    /* tp_new */
(freefunc)int_free,                         /* tp_free */
};

三个特殊操作

PyTypeObject中有三个函数族,对应了功能不同的三组函数:

  • tp_as_number -> PyNumberMethods
  • tp_as_sequence -> PySequenceMethods -> __getitem__
  • tp_as_mapping -> PyMappingMethods

第一组对应了数字类型应该支持的函数:

typedef PyObject * (*binaryfunc)(PyObject *, PyObject *);
typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);
typedef PyObject * (*unaryfunc)(PyObject *);

typedef struct {
binaryfunc nb_add;          // __add__
binaryfunc nb_subtract;
binaryfunc nb_multiply;
binaryfunc nb_divide;
binaryfunc nb_remainder;
binaryfunc nb_divmod;
ternaryfunc nb_power;
unaryfunc nb_negative;
unaryfunc nb_positive;
unaryfunc nb_absolute;
inquiry nb_nonzero;         // __nonzero__
unaryfunc nb_invert;
binaryfunc nb_lshift;
binaryfunc nb_rshift;
binaryfunc nb_and;
binaryfunc nb_xor;
binaryfunc nb_or;
coercion nb_coerce;
unaryfunc nb_int;
unaryfunc nb_long;
unaryfunc nb_float;
unaryfunc nb_oct;
unaryfunc nb_hex;

/* Added in release 2.0 */
binaryfunc nb_inplace_add;         // __iadd__
binaryfunc nb_inplace_subtract;
binaryfunc nb_inplace_multiply;
binaryfunc nb_inplace_divide;
binaryfunc nb_inplace_remainder;
ternaryfunc nb_inplace_power;
binaryfunc nb_inplace_lshift;
binaryfunc nb_inplace_rshift;
binaryfunc nb_inplace_and;
binaryfunc nb_inplace_xor;
binaryfunc nb_inplace_or;

/* Added in release 2.2 */
/* The following require the Py_TPFLAGS_HAVE_CLASS flag */
binaryfunc nb_floor_divide;         // __floor__
binaryfunc nb_true_divide;
binaryfunc nb_inplace_floor_divide;
binaryfunc nb_inplace_true_divide;

/* Added in release 2.5 */
unaryfunc nb_index;                 // __index__
} PyNumberMethods;

第二组对应了序列类型应该支持的操作:

typedef struct {
lenfunc sq_length;                  // __len__
binaryfunc sq_concat;
ssizeargfunc sq_repeat;
ssizeargfunc sq_item;               // __getitem__
ssizessizeargfunc sq_slice;
ssizeobjargproc sq_ass_item;
ssizessizeobjargproc sq_ass_slice;
objobjproc sq_contains;             // __contains__

/* Added in release 2.0 */
binaryfunc sq_inplace_concat;
ssizeargfunc sq_inplace_repeat;
} PySequenceMethods;

第三组对应了字典类型应该支持的操作:

typedef struct {
lenfunc mp_length;                  // __len__
binaryfunc mp_subscript;
objobjargproc mp_ass_subscript;
} PyMappingMethods;

PyType_Type

除了第1节的那些Type对象,还有以下两个内置Type对象:

// Include/object.h
PyAPI_DATA(PyTypeObject) PyType_Type; /* built-in 'type' */
PyAPI_DATA(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */

第一个对象PyType_Type是所有Py*_Type对象的类型,被这些对象头部ob_type域指向。

>>> class A(object):
...     pass
...
>>> type(A)
<type 'type'>
>>> type(object)
<type 'type'>
>>> type(int)
<type 'type'>
>>>> type(type)
<type 'type'>

第二个对象PyBaseObject_Type是Python中所有的对象(新风格定义的对象)的基类, 被这些对象的base域指向。

>>> id(object)
9675776
>>> int.__base__
<type 'object'>
>>> id(int.__base__)
9675776
>>> id(dict.__base__)
9675776
>>> class A(object):
...     pass
...
>>> id(A.__base__)
9675776
>>> id(type.__base__)
9675776

发表评论