dir()中hasattr()和'attribute'之间有什么区别?

时间:2013-07-18 12:34:12

标签: python

例如:

>>> s = 'string'
>>> hasattr(s, 'join')
True
>>> 'join' in dir(s)
True

Python documentation表示hasattr已实现调用getattr并查看是否引发异常。但是,这会导致很大的开销,因为获得的值被丢弃并且可能会引发异常。

问题是,如果调用'attribute' in dir(obj)意味着同样的事情,它是否更快,更安全,还是可能在特定场合失败?

4 个答案:

答案 0 :(得分:10)

这不是一回事。 dir()省略<{1}}和getattr()找到的属性的诊断工具。

来自dir() documentation

  

默认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()

为什么?

  1. 避免额外的try-except block / for循环的开销。
  2. 在python中,比权限更容易请求宽恕。