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