一切皆对象
表象展示
Python 是一门面向对象的程序设计语言,它的设计理念之一便是“一切皆对象”。
一个最简单的字符串就是一个str类的对象:
运行代码
a = 'abc'
print(type(a)) # <class 'str'>我们可以对a进行upper()等操作,因为str类实现了这些方法:
运行代码
a = 'abc'
print(a.upper()) # ABC事实上,Python 的基础数据类型全部是类:
运行代码
print(str, int, float, bool, list, dict)
# <class 'str'> <class 'int'> <class 'float'> <class 'bool'> <class 'list'> <class 'dict'>甚至包括作为关键字的True也是bool类的对象:
运行代码
print(type(True)) # <class 'bool'>就连函数也难逃一劫:
运行代码
def f():
...
print(type(f)) # <class 'function'>看,到处都是class。
原理刨析
::: waring 新手不友好,看不懂请快跑。 :::
先看看下面朴而不素的代码:
运行代码
class F:
...
class A(F):
...
class B(F, object):
...
a = A()
print(F.__bases__) # (<class 'object'>,)
print(A.__bases__) # (<class '__main__.F'>,)
print(B.__bases__) # (<class '__main__.F'>, <class 'object'>)
print(object.__bases__) # ()
print(type(a)) # <class '__main__.A'>
print(type(A)) # <class 'type'>
print(type(object)) # <class 'type'>
print(type.__bases__) # (<class 'object'>,)通过上面的很简单的代码,运用一眼洞穿法,我们可以根据每个打印语句的结果得到一些简单的观察结论:
- 如果定义一个类时没有指定继承哪个类,则默认继承
object类 object类的父类为空,说明object类位于继承关系链的顶端,object类是 Python 中所有类的父类,可以说object是 Python 中的顶端类- 对象
a由类A实例化而来,a的类型为A,这个比较容易理解 - 根据 3 的观察结果,同样的观察手法运用在类
A上,观察到类A是由type这个类实例化而来,类A的类型为type,说明类A是一个类的同时也是一个对象(类A是类type的实例化对象)。这里可能有点晕但是请先接着看下去吧 - 根据 3 的观察结果,同样的观察手法运用在顶端类
object上,观察到object这个顶端类也是由type这个类实例化而来,类object的类型也为type,也说明object作为一个类的同时也是一个对象 - 类
type作为实例化类A和类object的类,其父类为object
看完上面的这些观察结论,相信有一部分童鞋已经两眼发懵了,什么类 A 是一个类也是一个对象,object 类的类型是 type,而 type 类的父类又是 object……
这里先来一张图简单表示一下这几者的关系,舒缓一下情绪:

蓝色箭头由实例对象指向实例化它的类,红色箭头由子类指向父类。
值得注意的是,这个图有几个关键的地方:
- 类(如
class A,class object)都是由type这个类实例化而来的,即所有类(class)对象的类型都是type type这个类也是由type自己实例化而来的(图中type处指向自身的部分),即type类的类型也为typetype类的父类是object类
有了以上的铺垫,我们可以知道一个最普通的实例对象链是这样子的:
type --实例化--> object --衍生(继承)--> class A (类) --实例化--> a(具体对象)
这部分都是比较好理解的,但关键的问题是——object 类作为 type 类的父类,怎么会是由 type 类实例化出来的?还有 type 类居然是由 type 自己实例化出来的?这都是什么操作?
我们可以看看在源码中,type 类和 object 类分别是什么(Python 的底层是 C 的实现,下面的源码如果看不懂的话请别在意,因为不妨碍理解):
在源码中,type 类的定义如下:
#define PyVarObject_HEAD_INIT(type, size)
1, type, size,
PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"type", /* tp_name */
sizeof(PyHeapTypeObject), /* tp_basicsize */
sizeof(PyMemberDef), /* tp_itemsize */
0, /* tp_base */
...
}object 类的定义如下:
PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"object", /* tp_name */
sizeof(PyObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_base */
...
}这两个类结构体中的各项的具体含义这里不做深究,因为不在本文研究范围内。我们只需要关注这两个结构中的第一行: PyVarObject_HEAD_INIT(&PyType_Type, 0)。它表示这个类结构的对象类型。能看出来 object 类 和 type 类的对象类型都是 &PyType_Type,而 PyType_Type 正是底层表示 type 类的结构体!
这两个结构体就说明了:object 类将类型(即谁实例化了这个类)设置成了 type 类,type 类将类型设置成了自己!这其实是 Python 底层实现的一个小小的 trick ~
然后在 type 类的初始化过程中,执行了如下代码:
type->tp_base = &PyBaseObject_Type;转换为 Python 为:
type.__base__ = (object, )这句话显式地将 object 类指定为 type 类的父类,这不就是第一个问题的答案所在吗?
源码看到这里,前面的两个问题就已经全部解决了,我们可以开始全面总结一下 type class object 的关系了:
object类是所有类(class)的父类,包括type类,object类的父类为空type类是所有类的类型,即为所有类(class)都可由type实例化而来,包括type类自己
将上面的关系总结成一张图就是:

梅开二度了,那么也还是再提醒一下:蓝色箭头由实例对象指向实例化它的类,红色箭头由子类指向父类。
不理解的可以再看另一个作者的图:实线箭头表示继承关系,由子类指向父类;虚线箭头表示实例化,由实例对象指向实例化它的类。

版权所有
版权归属:异想之旅 | YuzhenQin