Answers:
第一个比第二个更有效。 del foo.bar
编译为两个字节码指令:
2 0 LOAD_FAST 0 (foo)
3 DELETE_ATTR 0 (bar)
而delattr(foo, "bar")
需要五个:
2 0 LOAD_GLOBAL 0 (delattr)
3 LOAD_FAST 0 (foo)
6 LOAD_CONST 1 ('bar')
9 CALL_FUNCTION 2
12 POP_TOP
这意味着第一个运行速度会稍快(但这并不是一个很大的差异–在我的机器上为.15μs)。
就像其他人所说的那样,您真正应该只在动态确定要删除的属性时才使用第二种形式。
[编辑以显示函数内部生成的字节码指令,编译器可在其中使用LOAD_FAST
和LOAD_GLOBAL
。
dis
模块。您可以使用python -m dis
并输入一些代码从命令行运行它,或者使用来反汇编函数dis.dis()
。
请考虑以下示例:
for name in ATTRIBUTES:
delattr(obj, name)
要么:
def _cleanup(self, name):
"""Do cleanup for an attribute"""
value = getattr(self, name)
self._pre_cleanup(name, value)
delattr(self, name)
self._post_cleanup(name, value)
您不能使用del做到这一点。
del self.__dict__[name]
,当然假设元类没有有趣的事情
无疑是前者。在我看来,这就像在询问是否foo.bar
比更好getattr(foo, "bar")
,而且我认为没有人在问这个问题:)
if hasattr(obj, 'var') and obj.var == ...
... if getattr(obj, 'var', None) == ...
在大多数情况下,我可以将其简化为!我认为,它略短且易于阅读。
hasattr
实际上致电getattr
这实际上是一个优先事项,但第一个可能更可取。如果您不知道要提前删除的属性的名称,我只会使用第二个。