Python 什么';hasattr()和';属性';在dir()中?

Python 什么';hasattr()和';属性';在dir()中?,python,Python,例如: >>> s = 'string' >>> hasattr(s, 'join') True >>> 'join' in dir(s) True 表示通过调用getattr并查看它是否引发异常来实现hasattr。但是,这会导致很大的开销,因为获取的值会被丢弃,并且可能引发异常 问题是,在dir(obj)中调用'attribute'是否意味着同样的事情,它是更快、安全的,还是在特定情况下可能会失败?hasattr的速度快了100多倍:)

例如:

>>> s = 'string'
>>> hasattr(s, 'join')
True
>>> 'join' in dir(s)
True
表示通过调用
getattr
并查看它是否引发异常来实现
hasattr
。但是,这会导致很大的开销,因为获取的值会被丢弃,并且可能引发异常


问题是,在dir(obj)中调用
'attribute'是否意味着同样的事情,它是更快、安全的,还是在特定情况下可能会失败?

hasattr的速度快了100多倍:)


这不完全是一回事
dir()
是一种诊断工具,它忽略了
getattr()
hasattr()
可能找到的属性

从:

默认的
dir()
机制对不同类型的对象表现不同,因为它试图生成最相关的信息,而不是完整的信息:

  • 如果对象是模块对象,则列表包含模块属性的名称
  • 如果对象是类型或类对象,则列表包含其属性的名称,并递归地包含其基的属性的名称
  • 否则,该列表将包含对象的属性名称、其类的属性名称以及其类的基类的递归属性名称

注意:由于提供
dir()
主要是为了方便在交互式提示下使用,因此它尝试提供有趣的 一组名称,而不是试图严格或一致地提供 已定义的名称集,其详细行为可能会随着 释放。例如,
元类
属性不在结果中 当参数是类时,请列出

我的

这意味着
hasattr()
将找到元类提供的属性,但
dir()
不会,并且所找到的内容可能与Python版本不同,因为函数的定义是提供调试方便,而不是完整性

特定元类场景的演示,其中
hasattr()
查找元类定义的属性:

>>> class Meta(type):
...     foo = 'bar'
... 
>>> class Foo(metaclass=Meta):
...     pass
... 
>>> hasattr(Foo, 'foo')
True
>>> 'foo' in dir(Foo)
False
最后但并非最不重要的是:

如果对象有一个名为
\uuuu dir\uuu()
的方法,则将调用此方法,并且必须返回属性列表

这意味着,如果实现了
\uuuuu dir()
方法,则
hasattr()和
dir()
在“找到”哪些属性方面的差异可能更大

只要坚持使用hasattr()
。首先,它更快,因为测试一个属性很便宜,因为这只是针对一个或多个字典的成员资格测试。另一方面,枚举所有字典键并跨实例、类和基类合并它们的CPU成本要高得多。

dir()
不调用
getattr()
,或者类似的任何东西,它取决于类本身的“描述”:

在查找文档时,只能使用
dir()

hasattr()基本上是

try:
    s.attribute
    return True
except AttributeError:
    return False
而“目录中的属性”更像:

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()
为什么?

  • 以避免除块/for循环之外的额外尝试的开销
  • 在python中,请求原谅比请求允许更容易

  • 使用
    hasattr
    的一个缺点是,它会触发属性执行,这可能会带来成本。在Django
    OneToOneField
    关系等情况下,这甚至会触发数据库查询。我不认为有其他选择,是吗?@AugustoMen:您可以使用特定于应用程序的方法来测试存在的属性。例如,我确信Django有一种枚举字段的方法。
    if hasattr(s, 'attributeName'):
        s.attributeName()
    else:
        do_stuff()
    
    try:
        s.attributeName()
    except AttributeError:
        do_stuff()