在Python社区待久了你就会发现一个很有意思的现象:很多写了三五年业务代码的人,装饰器、上下文管理器、生成器都用得很溜,但被问到“type和object到底什么关系”这种问题时,常常会愣住。
我最早也被这个问题卡过。那会儿刚把Python当脚本语言用,觉得“类”就是用来创建对象的模板,直到某天读到一句话——Python里类也是对象。这个看似绕口的表述,背后藏着一套非常漂亮的、自我构建的对象模型。用编译原理里的话说,这叫“自举”:用Python自己的对象规则,来描述对象规则本身。
认真梳理完这块内容之后,我的感受是:这不仅仅是理论炫技。它决定了你对元类、描述符、__init_subclass__、动态创建类这些高级特性的理解深度,也直接影响你在写框架、调库、以及排查一些诡异报错时的底气。这篇就从一个研究项目的角度,把我拆解“Python对象模型自举结构”的完整过程写下来。不管你是刚装好Python准备入门的初学者,还是写了几年代码的进阶选手,这都值得花半小时读透。
1. 先搞清楚“一切皆对象”到底意味着什么
1.1 用 dir 和 type 撕开对象的表皮
我常说,想理解Python的对象模型,不要去看八股文,直接开一个交互式解释器,把内置类型一个个“盘”一遍。
python复制>>> type(1)
<class 'int'>
>>> type([])
<class 'list'>
>>> type(type(1))
<class 'type'>
>>> type(int)
<class 'type'>
前两行好理解:整数1是int类的实例,空列表是list类的实例。关键在于后面两行:int这个类本身,居然也有类型,它的类型是type。也就是说,Python中的类不仅仅是“创建实例的模板”,它自己也作为对象存在,可以被传递、被赋值、被动态创建。
再往下看:
python复制>>> int.__class__
<class 'type'>
>>> type.__class__
<class 'type'>
>>> object.__class__
<class 'type'>
连type自己、连所有类的基类object,它们各自的__class__也还是type。你可以把__class__理解为“这个对象是谁造出来的”。实例是由类造的,而类是由type造的。于是出现了一个非常奇特的结构:type是它自己的类,同时type又是所有类的类。
我第一次跑出这些结果的时候,第一反应是:这不就是递归吗?为什么没有无限递归下去?这恰恰是“自举结构”最精髓的地方——它在体系内部完成闭环,不需要一个体系外的“裁判”。
1.2 什么叫“构建规则也由对象描述”
做一个不太严谨但很直观的类比。写文档的时候,我们经常用Markdown语法描述一篇文档的结构,但Markdown语法本身也是一篇文档,它也可以用Markdown来描述。你拿#来定义标题,而这个#的语法规则,也可以用一篇Markdown写出来。
Python的对象模型就是这样:用来创建对象的规则(类),本身也是一个对象;用来创建类的规则(元类,默认是type),本身还是一个类;而这个元类的构造规则,又回到了type自己身上。整个体系在自身内部互相指涉,完成了自洽。
这对日常开发的影响是深远的。因为类和普通对象遵守同一套规则,所以你就能对类做很多“对普通对象才能做的事”:动态给类加方法、把类当作参数传递、在运行时创建全新的类。这些能力在其他很多语言里是不可想象的,但在Python里是家常便饭。例如:
python复制def dog_speak(self):
return "汪汪"
# 运行时给类动态绑方法
Dog = type("Dog", (), {"speak": dog_speak})
d = Dog()
print(d.speak()) # 汪汪
这里type(...)的用法不是查看类型,而是在“创建类”。类被当成了普通对象来构造,这正是对象模型自举结构带来的直接红利。
1.3 自举不是Python的专利,但Python把它做到了极致
聊到这里有人会问:别的动态语言不也这样吗?确实,Ruby的对象模型也非常优雅,Smalltalk更是这个思想的鼻祖。但Python的特殊之处在于,它把“自举”这件事做得极其彻底、极其一致:
- 一切皆对象,包括类、函数、模块、异常类型;
- 所有对象的创建路径都收敛到
type上; type这个“创建者”自身又遵守对象规则。
一致性带来的是心智负担的降低。你只需要掌握一套规则,就能推演出绝大多数行为。我在写爬虫框架、写量化回测系统的时候,经常利用这种一致性去批量化地生成类、动态注册策略,省掉了大量重复代码。说实话,理解了这个结构之后,再回头看很多框架源码,有种“任督二脉被打通”的感觉,以前觉得是黑魔法的地方,其实都是对象模型自举的必然结果。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. type 和 object:对象模型里最核心的循环
2.1 用代码验证那个绕口令
现在进入整个对象模型最核心的“循环”。用一段代码就能验证:
python复制print(isinstance(object, type)) # True:object是type的实例
print(isinstance(type, object)) # True:type是object的子类实例?
print(issubclass(type, object)) # True:type继承自object
print(type.__base__) # <class 'object'>:type的基类是object
print(object.__class__) # <class 'type'>:object的类是type
这段代码输出了一个循环关系:`objec
