__mro__和mro为什么不在类对象的dir()中列出?

huangapple go评论110阅读模式
英文:

Why aren't __mro__ and mro listed in the dir() of a class object

问题

如果mro__mro__C的有效属性,为什么它们不会显示在dir()函数的输出中呢?

我已经看过了这个帖子,其中接受的答案说这是因为__mro__mroC的元类type的属性,typeC的元类(这意味着C的类objecttype的一个实例),而不是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的类型,这意味着sSample的一个实例,这与前面代码示例中的Ctype的关系相同。如你所见,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', ...]

huangapple
  • 本文由 发表于 2023年7月7日 02:17:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631553.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定