为何类对象的dir()输出中不包含__mro__与mro属性?
为什么
dir(C)不显示__mro__和mro属性? 先看这段代码:
class C: pass print(C.mro()) # 输出: [<class '__main__.C'>, <class 'object'>] print(C.__mro__) # 输出: (<class '__main__.C'>, <class 'object'>) print(dir(C)) # 输出内容过长 :( print("__mro__" in dir(C) or "mro" in dir(C)) # 输出: False
明明mro和__mro__是类C的有效属性,能正常调用和访问,为什么它们没有出现在dir()函数的输出里?
有人解释说__mro__和mro是元类type的属性(类C是type的实例),而非C的超类属性,所以type的__dict__不会被合并到dir(C)的结果中。但这里有个疑问,看对比代码:
class Sample: a = 5 def f(): pass s = Sample() print(dir(s)) # 输出内容过长 print("f" in dir(s)) # 输出: True print("a" in dir(s)) # 输出: True
实例s是Sample的实例,Sample的属性能出现在dir(s)中;那类C是type的实例,按这个逻辑,type的__mro__和mro也应该出现在dir(C)中才对,可实际并没有。这是为什么?
核心原因:dir()函数对「类(元类实例)」和「普通实例」的处理逻辑不同
- 普通实例的
dir()逻辑
当调用dir(s)(s是Sample的实例)时,dir()会:
- 先收集实例自身
__dict__中的属性 - 再递归收集实例所属类(Sample)及其所有父类的
__dict__中的属性
所以Sample的类属性a和方法f会被包含在dir(s)的结果里。
- 类(元类实例)的
dir()逻辑
当调用dir(C)(C是type的实例)时,dir()会:
- 先收集类自身
__dict__中的属性 - 再递归收集类的所有父类(这里是object)的
__dict__中的属性
但不会去收集元类(type)及其父类的__dict__中的属性
- 属性查找 vs
dir()的区别
你能正常调用C.mro()或访问C.__mro__,是因为Python的属性查找机制和dir()的逻辑不一样:
- 属性查找时,访问类的属性会遵循「类自身→父类→元类→元类父类」的顺序,所以能找到
type里的mro和__mro__ - 但
dir()的设计目标是展示「类/实例自身以及继承链上的属性」,这里的继承链指的是类的父类链,而非元类链,所以不会包含元类的属性
内容的提问来源于stack exchange,提问作者Amir Kooshky
相关产品推荐
相关产品推荐

