为何新式类的MRO中不存在type?类与元类相关技术疑问
好问题!这几个点刚好戳中了Python里类、元类和继承最容易混淆的地方,我一个个给你掰明白:
1. 为什么新式类的MRO里找不到
type? 先明确一个核心:MRO(方法解析顺序)是给「类的实例」用的,描述的是实例查找属性/方法时的继承链,而type是类的「元类」——元类是用来创建类的“类”,它和实例的继承链根本不是一回事。
举个具体的例子:
class A(object): pass a = A()
a是A的实例,A.__mro__描述的是a找方法时的顺序:A → object,这和type完全无关,因为type是管A这个类本身的,不管a的方法查找。- 而
A这个类本身是type的实例(所以A.__class__ is type),如果要找A这个“对象”的方法解析顺序,得看它的元类链:type → object(你可以打印type.__mro__看到)——这才是A作为一个对象查找方法时的顺序,但这和实例的MRO不是一回事。
简单说:MRO是实例的继承路线图,元类是类的“创造者”,两者分属不同层级,所以type不会出现在类的MRO里。
2. 新式类为什么继承
object而非type? 因为继承是「实例层面的能力传递」,元类是「类的创建规则」,这俩的作用完全不同:
- 新式类继承
object,是为了让它的所有实例都能拥有object提供的基础能力——比如__init__初始化、__str__字符串表示、__eq__相等判断这些所有对象都该有的方法,这是实例的“基础配置”。 - 如果让类继承
type,那这个类就不再是普通的类了,它会变成一个元类——这时候你用它创建的不是普通实例,而是另一个类!比如:
这显然不是我们定义普通类的目的,所以新式类默认继承# 继承type的类是元类,不是普通类 class A(type): pass # 此时A()创建的是一个新类,而不是普通实例 new_class = A('NewClass', (), {}) print(type(new_class)) # 输出: <class 'type'>object,而不是type。
3.
object和type的核心区别(以及元类与object的关系) 要搞懂这个,得先理清Python里的三层对象结构:
- 普通实例:比如
a = A(),它的父类链是A → object - 类:比如
A,它是元类(默认是type)的实例,类的父类是其他普通类(比如object) - 元类:比如
type,它是用来创建类的“类”,元类的父类是其他元类(type比较特殊,它是自己的实例,同时继承object)
核心区别一句话:
object是所有对象的最终父类:不管是普通实例,还是类(因为类本身也是type的实例,而type继承object),所有对象的根源都是object,它负责提供所有对象的基础方法。type是所有普通类的默认元类:它负责定义类的创建规则、类的行为(比如类怎么被实例化、怎么处理继承),是“类的制造者”。
而元类和object的关系:元类是类的“类”,但元类本身也是object的子类——比如type.__mro__是(type, object),所以元类的实例(也就是类)也会间接继承object的能力。
4. 关于旧式类的补充(针对Python 2.x)
Python 3里已经没有旧式类了,所有类都是新式类,但Python 2.x里的旧式类有这些特点:
- 旧式类不继承
object,比如class A: pass就是旧式类 - 旧式类的MRO是深度优先搜索,而且没有
__mro__属性,得用inspect.getmro()才能查看 - 旧式类的元类是
classobj(而不是type),A.__class__会返回<type 'classobj'> - 旧式类的实例没有默认的
__dict__,也不支持super()、描述符、属性装饰器等新式类特性 - 旧式类的实例不继承
object的方法,比如默认的__str__只会返回<instance of A at 0x...>,而不是新式类的<__main__.A object at 0x...>
内容的提问来源于stack exchange,提问作者nobody31985
相关产品推荐
相关产品推荐

