在python中、处理的一切都是对象_Python 3+ 一切都是对象
對于 Python 來說,一切都是對象 。 這句話很重要,當你對某個特性不了解時,回想下這句話也許就能想通
一個整數一個對象,一個浮點數也是一個對象,一個函數也是一個對象
>>> isinstance(3,object)
True
>>> isinstance(3.14, object)
True
>>> isinstance(max,object)
True
既然一切都是對象,那么這一切應該都有一個類來創建。它們都有一個公共的基礎類,這個基礎類就是 object
一切都是對象
object
如果我們使用 type() 函數來檢查下它們的類型,就會發現
>>> type(1)
>>> type(1)
>>> type(3.14)
>>> type(max)
那么 int 、float 和 builtin_function_or_method 又是什么呢?
>>> type(int)
>>> type(int)
>>> type(float)
>>> type(builtin_function_or_method)
Traceback (most recent call last):
File "", line 1, in
NameError: name 'builtin_function_or_method' is not defined
但,其實,object 也是一個對象
>>> type(object)
type()
看到這里,想必對 type 這個類型很好奇,到底是什么鬼?
一探究竟的事情,我們等下再說,我們先來了解下 type() 函數的原理
type() 函數是一個內建可調用類,只有一個參數的情況下,它的作用相當于訪問參數的 __class__ 屬性
>>> type(int)
>>> int.__class__
更有意思的是,type(type) 的結果還算是
>>> type(type)
>>> type.__class__
什么意思,也就是自己創建了自己? 這....
越挖越深,算了,以后有篇幅再來講解 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 "." */
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)
>>> type(object)
>>> type(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 其實沒有任何的,對吧,我們再下一章節再來學習
總結
以上是生活随笔為你收集整理的在python中、处理的一切都是对象_Python 3+ 一切都是对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中立方表示_在Python中
- 下一篇: python是怎么写出来的_请问这个怎么