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

时间:2011-08-17 16:16:21

标签: python

假设我有一个简单的课程:

class Foobar(object):
    pass

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

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

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

Foobar.__name__

并获取Foobar

为什么Python的表现如此?

4 个答案:

答案 0 :(得分:7)

dir无法保证返回所有可能的属性。来自the docs

  

因为提供dir()主要是为了方便使用   交互式提示,它试图提供一组有趣的名称   不只是它试图提供严格或一致定义的集合   名称及其详细行为可能会在不同版本中发生变化。对于   例如,元类属性不在结果列表中   论证是一个阶级。

答案 1 :(得分:3)

根据有关dir() method的python文档,您可以在对象上实现__dir __()方法,该方法返回在对象上调用目录时要查看的项目列表。

__name__成员是某些special attributes python对象的一部分,正如文档中所述:

  

dir()内置函数未报告其中一些。

答案 2 :(得分:1)

关于这个问题最近的一个问题的答案让我想要更详细地阐述这个答案。首先,接受的答案是正确的。 dir只调用__dir__钩子方法,默认的__dir__钩子方法通常只返回对象__dict__的键。

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

据我所知the source code,在创建类时,有许多描述符由type设置。其中一个描述符是__name____name__ getter调用type_name,setter调用type_set_name。这些getter / setter实际上在类型对象实例(即类)的tp_name槽中获取/设置名称。由于这实际上是类型对象上的一个特殊插槽,因此它实际上并不存在于类__dict__中,因此varsdir不会报告它。

请注意,类型对象实例(即类)的dir具体不会添加来自__class__属性的成员,因为"methods belonging to the metaclass would probably be more confusing than helpful"

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

  • object没有__name__属性,但type没有。
  • type的{​​{1}}属性实际上是一个描述符。
  • 由于__name__的元类是object,因此在请求type时,会调用object.__name__的{​​{1}}描述符。
  • type描述符在__name__广告位中查找名称。创建类时,name插槽由type->tp_name填充。
  • type->tp_name专门写入类的​​元类的 not 报告属性,因为python开发人员认为这样做会带来更多弊大于利。

答案 3 :(得分:0)

我在写 pytests 时遇到过这个问题。尽管人们解释了原因,但没有建议解决方法。我发现的唯一解决方法是将 .py 文件移动到另一个目录,然后导入它们。