为什么cls .__ name__没有出现在dir()中?

Fab*_*ian 11 python

假设我有一个简单的类:

class Foobar(object):
    pass
Run Code Online (Sandbox Code Playgroud)

如果我使用dir(Foobar),我会得到以下输出:

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
Run Code Online (Sandbox Code Playgroud)

即使它没有出现在输出中dir(),我也可以访问__name__:

Foobar.__name__
Run Code Online (Sandbox Code Playgroud)

得到Foobar.

为什么Python表现那样?

unu*_*tbu 8

dir不保证返回所有可能的属性.来自文档:

因为dir()主要是为了方便在交互式提示中使用而提供的,所以它尝试提供一组有趣的名称,而不是尝试提供严格或一致定义的名称集,并且其详细行为可能会在不同版本之间发生变化.例如,当参数是类时,元类属性不在结果列表中.


mgi*_*son 5

最近对这个问题的回答让我想进一步详细说明这个答案。首先,接受的答案是正确的。 dir简单地调用__dir__钩子方法,默认__dir__钩子方法通常只返回对象的__dict__.

其次,__name__不在子类中object.__dict__,也没有放在__dict__of 子类中。如果它不在 中__dict__,它在哪里以及如何查找?

据我了解源代码,有许多描述符是type在类创建期间设置的。这些描述符之一是__name__. 该__name__吸气调用TYPE_NAME和setter方法调用type_set_name。这些 getter/setter 实际上tp_name在类型对象实例(即类)的插槽中获取/设置名称。由于这实际上是类型对象上的一个特殊槽,它实际上并不存在于类中__dict__,因此它不会被varsor报告dir

请注意,dir对于类型对象实例(即类),特别是不会从 from__class__属性添加成员,因为“属于元类的方法可能比有用更令人困惑”

所以,让我们把这一切放在一起。

  • object没有__name__属性但type有。
  • type__name__属性实际上是一个描述符。
  • 由于object的元类是type,因此在object.__name__被请求时,将调用type__name__描述符。
  • name描述符中查找名称的type->tp_name插槽。该type->tp_name插槽由type.__new__创建类时填充。
  • object.__dir__专门编写为报告类元类的属性,因为 Python 开发人员认为这样做弊大于利。