对于 Python 来说,一切都是对象 。 这句话很重要,当你对某个特性不了解时,回想下这句话也许就能想通
一个整数一个对象,一个浮点数也是一个对象,一个函数也是一个对象
>>> isinstance(3,object) True >>> isinstance(3.14, object) True >>> isinstance(max,object) True
既然一切都是对象,那么这一切应该都有一个类来创建。它们都有一个公共的基础类,这个基础类就是 object
一切都是对象
object
如果我们使用 type()
函数来检查下它们的类型,就会发现
>>> type(1) <class 'int'> >>> type(1) <class 'int'> >>> type(3.14) <class 'float'> >>> type(max) <class 'builtin_function_or_method'>
那么 int
、float
和 builtin_function_or_method
又是什么呢?
>>> type(int) <class 'type'> >>> type(int) <class 'type'> >>> type(float) <class 'type'> >>> type(builtin_function_or_method) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'builtin_function_or_method' is not defined
但,其实,object
也是一个对象
>>> type(object) <class 'type'>
type()
看到这里,想必对 type
这个类型很好奇,到底是什么鬼?
一探究竟的事情,我们等下再说,我们先来了解下 type()
函数的原理
type()
函数是一个内建可调用类,只有一个参数的情况下,它的作用相当于访问参数的 __class__
属性
>>> type(int) <class 'type'> >>> int.__class__ <class 'type'>
更有意思的是,type(type)
的结果还算是 <class 'type'>
>>> type(type) <class 'type'> >>> type.__class__ <class 'type'>
什么意思,也就是自己创建了自己? 这....
越挖越深,算了,以后有篇幅再来讲解 type()
我们先挖一下源码,因为 type()
、int
、float
都说是内建函数,所以我们找到内建函数的源码
在 Python
目录下的 bltinmodule.c
文件中的第 2892 行开始
SETBUILTIN("None", Py_None); SETBUILTIN("Ellipsis", Py_Ellipsis); SETBUILTIN("NotImplemented", Py_NotImplemented); SETBUILTIN("False", Py_False); SETBUILTIN("True", Py_True); SETBUILTIN("bool", &PyBool_Type); SETBUILTIN("memoryview", &PyMemoryView_Type); SETBUILTIN("bytearray", &PyByteArray_Type); SETBUILTIN("bytes", &PyBytes_Type); SETBUILTIN("classmethod", &PyClassMethod_Type); SETBUILTIN("complex", &PyComplex_Type); SETBUILTIN("dict", &PyDict_Type); SETBUILTIN("enumerate", &PyEnum_Type); SETBUILTIN("filter", &PyFilter_Type); SETBUILTIN("float", &PyFloat_Type); SETBUILTIN("frozenset", &PyFrozenSet_Type); SETBUILTIN("property", &PyProperty_Type); SETBUILTIN("int", &PyLong_Type); SETBUILTIN("list", &PyList_Type); SETBUILTIN("map", &PyMap_Type); SETBUILTIN("object", &PyBaseObject_Type); SETBUILTIN("range", &PyRange_Type); SETBUILTIN("reversed", &PyReversed_Type); SETBUILTIN("set", &PySet_Type); SETBUILTIN("slice", &PySlice_Type); SETBUILTIN("staticmethod", &PyStaticMethod_Type); SETBUILTIN("str", &PyUnicode_Type); SETBUILTIN("super", &PySuper_Type); SETBUILTIN("tuple", &PyTuple_Type); SETBUILTIN("type", &PyType_Type); SETBUILTIN("zip", &PyZip_Type);
可以看到
int
是一个对PyLong_Type
的引用float
是一个对PyFloat_Type
的引用object
是一个对PyBaseObject_Type
的引用type
是一个对PyType_Type
的引用
继续追查,我们可以看到如下定义
Include/longobject.h
PyAPI_DATA(PyTypeObject) PyLong_Type;
Include/floatobject.h
PyAPI_DATA(PyTypeObject) PyFloat_Type;
Include/object.h
PyAPI_DATA(PyTypeObject) PyType_Type; /* built-in 'type' */ PyAPI_DATA(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */ PyAPI_DATA(PyTypeObject) PySuper_Type; /* built-in 'super' */
所以,接下来我们就想知道 PyAPI_DATA
是什么鬼,这个在 pyport.h
中定义
#ifndef PyAPI_DATA # define PyAPI_DATA(RTYPE) extern RTYPE #endif
也就是说,经过预处理之后,它们就是下面这样
PyTypeObject PyLong_Type; PyTypeObject PyFloat_Type PyTypeObject PyType_Type; PyTypeObject PyBaseObject_Type; PyTypeObject PySuper_Type;
是什么意思呢? 它们都是 PyTypeObject
结构体的一个变量,所以它们的终极类型,结果都是 type
因为它们都是函数,这些函数都会传入一个字面量,然后返回一个对应类型的实例
所以,我们就要知道 PyTypeObject
到底是什么
#ifdef Py_LIMITED_API typedef struct _typeobject PyTypeObject; /* opaque */ #else typedef struct _typeobject { PyObject_VAR_HEAD const char *tp_name; /* For printing, in format "<module>.<name>" */ Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ /* Methods to implement standard operations */ destructor tp_dealloc; printfunc tp_print; getattrfunc tp_getattr; setattrfunc tp_setattr; PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2) or tp_reserved (Python 3) */ reprfunc tp_repr; /* Method suites for standard classes */ PyNumberMethods *tp_as_number; PySequenceMethods *tp_as_sequence; PyMappingMethods *tp_as_mapping; /* More standard operations (here for binary compatibility) */ hashfunc tp_hash; ternaryfunc tp_call; reprfunc tp_str; getattrofunc tp_getattro; setattrofunc tp_setattro; /* Functions to access object as input/output buffer */ PyBufferProcs *tp_as_buffer; /* Flags to define presence of optional/expanded features */ unsigned long tp_flags; const char *tp_doc; /* Documentation string */ /* 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; /* Iterators */ getiterfunc tp_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; descrgetfunc tp_descr_get; descrsetfunc tp_descr_set; Py_ssize_t tp_dictoffset; initproc tp_init; allocfunc tp_alloc; newfunc tp_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; /* Type attribute cache version tag. Added in version 2.6 */ unsigned int tp_version_tag; destructor tp_finalize; #ifdef COUNT_ALLOCS /* these must be last and never explicitly initialized */ Py_ssize_t tp_allocs; Py_ssize_t tp_frees; Py_ssize_t tp_maxalloc; struct _typeobject *tp_prev; struct _typeobject *tp_next; #endif } PyTypeObject; #endif
结构体成员很多,我们只要记住第二个结构体成员 tp_name
就好,它表示当前的对象的类型
比如 PyLongType
在初始化的时候是这样的
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 */ long_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ 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 */ long_to_decimal_string, /* 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 */ };
可以看到第二个参数 tp_name
就被设置为 "int"
同样的,我们可以看到 PyBaseObject_Type
变量的初始化为
typeobject.c
PyTypeObject PyBaseObject_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "object", /* tp_name */ sizeof(PyObject), /* tp_basicsize */ 0, /* tp_itemsize */ object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ object_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)_Py_HashPointer, /* tp_hash */ 0, /* tp_call */ object_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ PyDoc_STR("object()\n--\n\nThe most base type"), /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ object_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ object_methods, /* tp_methods */ 0, /* tp_members */ object_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ object_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ object_new, /* tp_new */ PyObject_Del, /* tp_free */ };
tp_name
成员变量被设置为 object
同时在 typeobject.c
中还可以看到 PyType_Type
变量的初始化
PyTypeObject PyType_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "type", /* tp_name */ sizeof(PyHeapTypeObject), /* tp_basicsize */ sizeof(PyMemberDef), /* tp_itemsize */ (destructor)type_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ (reprfunc)type_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ (ternaryfunc)type_call, /* tp_call */ 0, /* tp_str */ (getattrofunc)type_getattro, /* tp_getattro */ (setattrofunc)type_setattro, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */ type_doc, /* tp_doc */ (traverseproc)type_traverse, /* tp_traverse */ (inquiry)type_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ type_methods, /* tp_methods */ type_members, /* tp_members */ type_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */ type_init, /* tp_init */ 0, /* tp_alloc */ type_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ (inquiry)type_is_gc, /* tp_is_gc */ };
到此为止,我们已经了解了每隔类型的内建函数 int()
、float()
的创建过程,也知道了 type()
函数第一次的返回值
PyObject_VAR_HEAD
接下来我们所要了解的是,为什么
>>> type(int) <class 'type'> >>> type(object) <class 'type'> >>> type(type) <class 'type'>
这就涉及到 type()
函数的实现了,我们知道,PyType_Type
、PyBaseObject_Type
和 PyLong_Type
都是的成员变量 tp_base
都是 0
,也就是说它们都没有基类
但是大家有没有发现另一个有趣的成员变量,就是 PyObject_VAR_HEAD
可以说,几乎所有的类型都有这个成员变量,它,就是继承链条,它用于表示当前类型在所有继承体系中的为止
我们来看看它的实现
Include/object.h
#define PyObject_VAR_HEAD PyVarObject ob_base;
而这个成员变量的初始化方式都是
PyVarObject_HEAD_INIT(&PyType_Type, 0)
也就是说,PyObject_VAR_HEAD
实际上是 PyVarObject
的一个实例
那 PyVarObject
又是什么呢?
typedef struct { PyObject ob_base; Py_ssize_t ob_size; /* Number of items in variable part */ } PyVarObject;
PyVarObject
包含了一个 PyObject
的实例,那么 PyObject
又是什么呢?
typedef struct _object { _PyObject_HEAD_EXTRA Py_ssize_t ob_refcnt; struct _typeobject *ob_type; } PyObject;
看到这,是不是很明朗了,struct _typeobject
就是 PyTypeObject
而 _PyObject_HEAD_EXTRA
的实现如下
#define _PyObject_HEAD_EXTRA \ struct _object *_ob_next; \ struct _object *_ob_prev;
所以,这条继承链就很清楚了,也能理解为什么 type(int)==type(type)
了
Python 中所有的对象,都是由此而成,可能你很费解,那么 int
和 object
其实没有任何的,对吧,我们再下一章节再来学习