例如:
>>> s = 'string'
>>> hasattr(s, 'join')
True
>>> 'join' in dir(s)
True
Python documentation表示hasattr
已实现调用getattr
并查看是否引发异常。但是,这会导致很大的开销,因为获得的值被丢弃并且可能会引发异常。
问题是,如果调用'attribute' in dir(obj)
意味着同样的事情,它是否更快,更安全,还是可能在特定场合失败?
答案 0 :(得分:10)
这不是一回事。 dir()
是省略<{1}}和getattr()
找到的属性的诊断工具。
默认
hasattr()
机制对不同类型的对象的行为有所不同,因为它会尝试生成最相关,而不是完整的信息:
- 如果对象是模块对象,则列表包含模块属性的名称。
- 如果对象是类型或类对象,则列表包含其属性的名称,并递归地显示其基础的属性。
- 否则,该列表包含对象的属性名称,其类的属性名称,以及其类的基类的属性的递归。
和
注意:因为提供
dir()
主要是为了方便在交互式提示中使用,所以它会尝试提供一个有趣的 一组名称超过它试图严格或一致地提供 定义的名称集,其详细行为可能会发生变化 版本。例如,dir()
属性不在结果中 当参数是一个类时列出。
强调我的。
这意味着metaclass
将找到元类提供的属性,但hasattr()
不会,并且找到的内容可能与Python版本不同,因为该函数的定义是提供调试方便,而不是完整性。
特定元类场景的演示,其中dir()
找到元类定义的属性:
hasattr()
最后但并非最不重要:
如果对象具有名为
>>> class Meta(type): ... foo = 'bar' ... >>> class Foo(metaclass=Meta): ... pass ... >>> hasattr(Foo, 'foo') True >>> 'foo' in dir(Foo) False
的方法,则将调用此方法,并且必须返回属性列表。
这意味着__dir__()
和hasattr()
在dir()
方法已实施的“找到”属性中可以更广泛地变化。
坚持.__dir__()
。例如,它更快,因为对属性的测试很便宜,因为这只是针对一个或多个字典的成员资格测试。枚举所有字典键并将它们跨实例,类和基类合并,另一方面具有更高的CPU成本。
答案 1 :(得分:4)
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
答案 2 :(得分:1)
dir()
不会调用getattr()
或类似内容,这取决于类“自我描述”:
>>> class Foo(object):
... def __dir__(self):
... return ['apples', 'bananas', 'mangoes']
... def __getattr__(self, attr):
... return {'a': 1}[attr]
...
>>> foo = Foo()
>>> hasattr(foo, 'a')
True
>>> hasattr(foo, 'apples')
False
>>> 'a' in dir(foo)
False
>>> 'apples' in dir(foo)
True
在查找文档时,您应该只使用dir()
。
答案 3 :(得分:0)
hasattr()基本上是
try:
s.attribute
return True
except AttributeError:
return False
while&#34;属性在dir(s)&#34;更像是:
for attr in dir(s):
if attribute == attr:
return True
return False
因此,预计hasattr会更快一些。
无论如何,如果我被允许偏离轨道,那么我会建议这样做。 如果你想做类似的事情:
if hasattr(s, 'attributeName'):
s.attributeName()
else:
do_stuff()
然后建议这样做:
try:
s.attributeName()
except AttributeError:
do_stuff()
为什么?