Python类型系统初步理解
我们知道,在python中,一切皆是对象。每一个对象都是一种类型的实例,包括创造对象的类型其本身,也是一个对象,也是另一种有创造出类型的类型的实例。
以一个int类型的实例,整数123为例子,123的类型是int,int是一种类型,也就是一个类,但是它本身也是一个对象,是另一种类型的实例,这种类型是type,type是一种类型,也是一种类型的实例,这种类型是它本身。
>>> n = 123
>>> type(n)
<type 'int'>
>>> type(type(n))
<type 'type'>
>>> type(type(type(n)))
<type 'type'>
type是一个比较特殊的类型,type既是类型,也是对象,同时它是是其所代表的类型的实例。这样的类型,在python中称为元类。
同时,在python中,一切类型都是object类的子类,因此,一切对象都是object的实例,包括type,以及object本身。
那么,一个有趣的问题出现了:
- type是object的实例
- type是type的实例
- object是object是实例
- object是type的实例
>>> isinstance(type, object)
True
>>> isinstance(type, type)
True
>>> isinstance(object, object)
True
>>> isinstance(object, type)
True
object和type的这种关系在python语言层面比较难以理解。但是我们知道cpython是用c语言实现的,这些概念在c语言层面都有对应的代码实现,通过理解c语言层面的实现,可以较好的理解object和type的关系,以及python的对象模型。
在c语言层面,有一个结构体PyObject,“pyhton语言中一切皆是对象”这句话,反映到c语言层面,其等价表示是“一切python语言层面的对象,在c语言层面,都可以用一个指向PyObject结构体的指针来表示”。
PyObject结构体的代码(并非真实源码,进行了方便理解的简化)如下:
typedef struct _object {
long ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
typedef struct _typeobject {
PyObject ob_base;
long ob_size;
const char *tp_name;
// ... (省略)
} PyTypeObject;
结构体PyObject就2项内容,一个引用计数器,用来进行垃圾收集的;一个指向另一个结构体的指针,用来表明这个对象是什么具体类型的,而这个结构体,其开头的部分,又是一个PyObject。
在c语言中,对于2个结构体A和B,如果B的开头一部分和A是一样的,那么它们的实例,在内存布局上,这一部分是一样的,从Python,Java等语言的概念上说,有点像继承。
#include <stdio.h>
typedef struct _person {
char *name;
int age;
} Person;
typedef struct _teacher {
char *name;
int age;
char *course;
} Teacher;
void print_person(Person *person) {
printf("I am %s, %d years old.\n", person->name, person->age);
}
int main() {
Teacher t = {
"tom",
25,
"Math"
};
print_person((Person *)&t);
return 0;
}
在上面的例子中,Teacher结构体的开头部分是和Person一样的,Teacher可以当Person使用。同样的,在python中,无论是什么对象,在c语言层面的表示,都是一个结构体的实例,而这个结构体,其开头的部分一定是一个PyOject,所以,多有的对象都可以当Pyobject使用。反应在python语言层面就是所有的对象都是object的实例。
type和object间的关系可以用下面一段代码模拟:
#include <stdio.h>
typedef struct _object {
long refcnt;
struct _type_object *ob_type;
} PyObject;
typedef struct _type_object {
long refcnt;
struct _type_object *ob_type;
const char *tp_name;
} PyTypeObject;
PyTypeObject py_type_type = {1, &py_type_type, "type"};
typedef struct _int_object {
long refcnt;
struct _type_object *ob_type;
long value;
} PyInt;
PyTypeObject py_type_int = {1, &py_type_type, "int"};
PyInt int_10 = {1, &py_type_int, 10};
void print_type_name(PyObject *ob) {
printf("<type '%s'>\n", ob->ob_type->tp_name);
}
int main() {
print_type_name((PyObject *)&int_10); // 相当于python中的type(10)
print_type_name((PyObject *)&py_type_int); // 相当于python中的type(int)
print_type_name((PyObject *)&py_type_type); // 相当于python中的type(type)
return 0;
}