本文来自异想之旅公开发布的Python教程,原文地址:https://www.yuque.com/yxzl/python
表象展示
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
。
原理刨析
新手不友好,看不懂请快跑
先看看下面朴而不素的代码:
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
类的类型也为type
type
类的父类是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
类自己
将上面的关系总结成一张图就是:
梅开二度了,那么也还是再提醒一下:蓝色箭头由实例对象指向实例化它的类,红色箭头由子类指向父类。
不理解的可以再看另一个作者的图:实线箭头表示继承关系,由子类指向父类;虚线箭头表示实例化,由实例对象指向实例化它的类。
后半部分参考和转载自: