英文:
Why aren't __mro__ and mro listed in the dir() of a class object
问题
如果mro和__mro__是C的有效属性,为什么它们不会显示在dir()函数的输出中呢?
我已经看过了这个帖子,其中接受的答案说这是因为__mro__和mro是C的元类type的属性,type是C的元类(这意味着C的类object是type的一个实例),而不是C的超类,因此type的__dict__属性不会与dir(C)的结果连接在一起。我仍然认为C作为type的一个实例不应该导致type的属性__mro__不会被列在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
正如你所看到的,Sample不是s的超类,而是s的类型,这意味着s是Sample的一个实例,这与前面代码示例中的C与type的关系相同。如你所见,Sample的属性在dir(s)中列出。因此,按照这个逻辑,我希望type的属性也会在dir(C)中列出,但正如我们之前看到的那样,__mro__和mro被省略了。
有人能够解释这是为什么吗?
英文:
Consider this piece of code:
class C:
pass
print(C.mro()) # Output: [<class '__main__.C'>, <class 'object'>]
print(C.__mro__) # Output: (<class '__main__.C'>, <class 'object'>)
print(dir(C)) # Output: too long :(
print("__mro__" in dir(C) or "mro" in dir(C)) # Output: False
If mro and __mro__ are valid attributes of C, why don't they show up in the dir() function's output?
I have already seen this post and the accepted answer says it's because __mro__ and mro are attributes of type which is the metaclass of C (meaning C's class object is an instance of type) and not its superclass so type's __dict__ attribute isn't concatenated with the result of dir(C). I still don't think C being an instance of type should cause type's attribute __mro__ to not be listed in dir(C). To illustrate this, consider the following code:
class Sample:
a = 5
def f():
pass
s = Sample()
print(dir(s)) # Output: too long
print("f" in dir(s)) # Output: True
print("a" in dir(s)) # Output: True
As you can see, Sample isn't s's superclass, it's s's type, so to speak, meaning s is an instance of Sample which is the same relationship that C from the previous code sample had to type. As you can see, the attributes of Sample are listed in dir(s). So by this logic I would expect the attributes of type to also be listed in dir(C) but as we saw previously __mro__ and mro are left out.
Can anybody shed some light on why this is?
答案1
得分: 1
dir(obj) 只是调用了 obj.__dir__。对于大多数对象,这将调用 object.__dir__,它会从 __dict__ 和对象的类型中收集属性。
type.__dir__(这是在调用 dir(C) 或 dir(Sample) 时所调用的内容)恰好不会收集类的类型上的属性(该类型将是 type 或类所具有的任何元类)。
如果你调用类的“常规” __dir__,你可以看到 mro/__mro__:
class C: pass
object.__dir__(C) # => [..., '__mro__', ..., 'mro', ...]
class TypeWithoutDir(type): __dir__ = object.__dir__
class D(metaclass=TypeWithoutDir): pass
dir(D) # => [..., '__mro__', ..., 'mro', ...]
英文:
dir(obj) just calls obj.__dir__. For most objects, this will call object.__dir__, which collects attributes from __dict__ and the type of the object.
type.__dir__ (Which is what is called when you call dir(C) or dir(Sample)) just happens to not collect attributes on the type of class (which will be type or whatever metaclass the class had).
If you call the "regular" __dir__ on your class, you can see mro/__mro__:
class C: pass
object.__dir__(C) # => [..., '__mro__', ..., 'mro', ...]
class TypeWithoutDir(type): __dir__ = object.__dir__
class D(metaclass=TypeWithoutDir): pass
dir(D) # => [..., '__mro__', ..., 'mro', ...]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论