例如:
>>> s = 'string'
>>> hasattr(s, 'join')
True
>>> 'join' in dir(s)
True
Run Code Online (Sandbox Code Playgroud)
Python文档说,hasattr实现调用getattr并查看它是否引发异常.然而,这导致了很大的开销,因为丢弃了所获得的值并且可能引发异常.
问题是,如果呼叫'attribute' in dir(obj)意味着同一件事,它是否更快,更安全,还是在特定场合可能失败?
Mar*_*ers 12
这不是一回事.dir()是一种诊断工具,忽略属性,这些属性getattr()和hasattr()会发现.
从dir()文档:
默认
dir()机制对不同类型的对象的行为有所不同,因为它尝试生成最相关的信息,而不是完整的信息:
- 如果对象是模块对象,则列表包含模块属性的名称.
- 如果对象是类型或类对象,则列表包含其属性的名称,并且递归地包含其基础的属性.
- 否则,该列表包含对象的属性名称,其类的属性的名称,以及其类的基类的属性的递归.
和
注:由于
dir()供应主要是在一个交互式提示使用便利性,它会尝试提供一个有趣的名称集更多比它试图提供一个严格或一致定义集名称,其行为细节可以跨版本改变.例如,metaclass当参数是类时,属性不在结果列表中.
强调我的.
这意味着hasattr()将找到元类提供的属性,但dir()不会,并且发现的内容可能与Python版本不同,因为函数的定义是提供调试的便利性,而不是完整性.
演示特定元类场景,在其中hasattr()找到元类定义的属性:
>>> class Meta(type):
... foo = 'bar'
...
>>> class Foo(metaclass=Meta):
... pass
...
>>> hasattr(Foo, 'foo')
True
>>> 'foo' in dir(Foo)
False
Run Code Online (Sandbox Code Playgroud)
最后但并非最不重要的:
如果对象具有名为的
__dir__()方法,则将调用此方法,并且必须返回属性列表.
这意味着,hasattr()和dir()可中"发现"如果什么属性更是有很大的不同.__dir__()方法已经实施.
坚持下去hasattr().例如,它更快,因为对属性的测试很便宜,因为这只是针对一个或多个字典的成员资格测试.另一方面,枚举所有字典键并将它们跨实例,类和基类合并具有更高的CPU成本.
hasattr 的速度快了 100 倍以上:)
In [137]: s ='string'
In [138]: %timeit hasattr(s, 'join')
10000000 loops, best of 3: 157 ns per loop
In [139]: %timeit 'join' in dir(s)
100000 loops, best of 3: 19.3 us per loop
Run Code Online (Sandbox Code Playgroud)