Python define el modelo
Cualquiera que haya estudiado Python sabe que todo en Python es un objeto. Por ejemplo, los objetos generados por las clases son objetos, la clase en sí es un objeto, int es un objeto, str es un objeto y dict es un objeto... Entonces, tengo curiosidad por saber cómo Python implementa estos objetos. Con esta curiosidad, decidí echar un vistazo al código fuente de Python. Después de todo, el código fuente es la forma más directa de satisfacer mi curiosidad.
En el archivo object.h, las dos estructuras de datos PyObject y PyVarObject se definen con el siguiente código:
1 #define PyObject_HEAD \ 2 Py_ssize_t ob_refcnt ?\ 3 struct _typeobject *; ob_type; 4 ?5 #define PyObject_VAR_HEAD ?\ 6 PyObject_HEAD ?\ 7 Py_ssize_t ob_size; 8 ?9 typedef struct _object {10 PyObject_HEAD11 }PyObject; Tipo : objetos de longitud fija y objetos de longitud variable. Todos los objetos en Python pertenecen a uno de estos dos tipos de objetos. Por ejemplo, int y float son objetos de longitud fija, y list, str y dict son objetos de longitud variable. A juzgar por las definiciones de las dos estructuras de datos de objetos anteriores, los encabezados de los objetos de longitud variable y los objetos de longitud fija son estructuras PyObject, es decir, todos los objetos en Python contienen inicialmente esta estructura y se puede acceder a ellos mediante el puntero PyObject *. Cualquier objeto, esta forma de acceder a los objetos se puede ver en todas partes del código fuente de Python. La estructura pyObject contiene dos miembros: punteros ob_refcnt y ob_type. ob_refcnt se usa para representar el número de veces que se hace referencia al objeto. Cuando ob_refcnt == 0, el objeto se destruirá inmediatamente; el puntero ob_type apunta a una estructura de tipo _typeobject, que representa el tipo de objeto, es decir, el tipo de objeto. tipo del objeto que lo generó. En realidad, esto es muy similar a la relación entre clases e instancias en orientación a objetos, PyObject es una instancia de una clase y ob_type representa esa clase. Pero a diferencia de la orientación a objetos, ob_type en sí también es un objeto.
Echemos un vistazo a la definición de _typeobject:
1 typedef struct _typeobject { 2 PyObject_VAR_HEAD 3 const char *tp_name /* Nombre del tipo*/ 4 Py_ ssize_tp_basicsize, tp_itemsize /* Tamaño del objeto instanciado*; / 5 ?6 /* Método estándar */ 7 ?8 destructor tp_dealloc; 9 printfunc tp_print; 10 getattrfunc tp_getattr; 11 setattrfunc tp_setattr; 12 cmpfunc tp_compare; ) Métodos*/16 17 PyNumberMethods *tp_as_number; 18 PySequenceMethods *tp_as_sequence; 19 PyMappingMethods *tp_as_mapping; función tp_str; 2 6 getattrofunc tp_getattro; tp_setattro; 28 ... ?
29 }PyTypeObject;
De la definición anterior, el comienzo de _typeobject también contiene la estructura PyObject, por lo que también es un objeto, ya que es también un objeto, entonces, según la comprensión orientada a objetos, ¿quién lo generará? La respuesta es que todos los objetos PyTypeObject se generan a través de PyType_Type, incluido el propio PyType_Type, lo cual es un poco indirecto ya que PyType_Type también es un objeto PyTypeObject. PyType_Type se define declarando PyType_Type como una variable estática global.
1 PyTypeObject PyType_Type = { 2 PyVarObject_HEAD_INIT(amp; PyType_Type, 0) 3 "tipo", /* tp_name */ 4 sizeof(PyHeapTypeObject), ?/* tp_basicsize */ 5 sizeof(PyMemberDef), / * tp_itemsize */ 6 (destructor)type_dealloc, ?/* tp_dealloc */ 7 0, ?/* tp_print */ 8 0, ?/* tp_getattr */ 9 0, ?/* tp_setattr */ 10 0, ?/* tp_compare */11 (reprfunc)type_repr, /* tp_repr */12 0, ?/* tp_as_number */13 0, ?/* tp_as_sequence */14 0, ?/* tp_as_mapping */15 (hashfunc)_Py_HashPointer, /* tp_hash */16 (ternaryfunc)type_call, /* tp_call */17 0, ?/* tp_str */18 (getattrofunc)type_getattro, /* tp_getattro */19 (setattrofunc)type_setattro, /* tp_setattro */20 0, ?/* tp_as_buffer */21 ... .22 }
De la definición de PyType_Type, ob_type se inicializa en su propia dirección, por lo que el tipo de PyType_Type es él mismo. Desde la implementación del código fuente de Python, el ob_type de todos los PyTypeObjects apuntará al objeto PyType_Type, por lo que PyType_Type es el tipo de todos los tipos, llamado metaclase.
Python define muchos objetos de tipo integrados, como objetos de tipo PyInt_Type (tipo int), PyStr_ Type (tipo str), PyDict_Type (tipo dict). Consulte la siguiente definición de tipo PyInt_Type:
1 PyTypeObject PyInt_Type. = { 2 PyVarObject_HEAD_INIT(amp; PyType_Type, 0) 3 "int", 4 sizeof(PyIntObject), 5 0, 6 (destructor)int_dealloc, /* tp_dealloc */ 7 (printfunc)int_print, ?/* tp_print */ 8 0 , ? /* tp_getattr */ 9 0, ?/* tp_setattr */ 10 (cmpfunc)int_compare, ?/* tp_compare */11 (reprfunc)int_too_decimal_string, /* tp_repr */12 amp; 0, ?/* tp_as_sequence */14 0, ?/* tp_as_mapping */15 (hashfunc)int_hash, /* tp_hash */16 0, ?/* La inicialización del objeto PyInt_Type?type es similar a PyType_Type?type, y el La definición del tipo PyInt_Type también se pasa. Implementado por variables estáticas globales. Todos los tipos integrados de Python se definen de esta manera. Los objetos generados por estos tipos se beneficiarán de los objetos de estos tipos, incluidos los métodos definidos por estos tipos.
¿Cómo comprobar el tipo de un objeto en Python? Hay dos métodos, uno es escribir directamente:
1 gt; gt; x = 12 gt; type(x)3 lt; >
El otro es a través del atributo __class__ del objeto:
1 gt; gt; x = 12 gt; ; 4 gt; gt; gt; ;gt;gt;tipo(int)3lt;tipo'tipo'gt;4gt;gt;tipo(str)5lt;tipo'tipo'gt;6gt;gt;gt;tipo(dict )7lt;type'type'gt ;8gt;gt;gt;type(type)9lt;type 'type'gt; A juzgar por los resultados de salida, los tipos int, str y dict son todos tipos, lo que confirma lo dicho antes. , todos los tipos pasan a través del elemento Generado por tipo de clase.