假设我有一个简单的课程:
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的表现如此?
答案 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__
中,因此vars
或dir
不会报告它。
请注意,类型对象实例(即类)的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 文件移动到另一个目录,然后导入它们。