这可能很愚蠢,但它一直在唠叨我的脑后。
Python为我们提供了两种从对象中删除属性的内置方法, del 命令字和 delattr 内置函数。我更喜欢 delattr ,因为我觉得它更明确一点:
del foo.bar
delattr(foo, "bar")
但我想知道他们之间是否存在引擎盖下的差异。
答案 0 :(得分:241)
第一个比第二个更有效。 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
]
答案 1 :(得分:33)
请考虑以下示例:
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 。
答案 2 :(得分:17)
毫无疑问是前者。在我看来,这就像问foo.bar
是否优于getattr(foo, "bar")
,我认为没有人问这个问题:)
答案 3 :(得分:14)
这确实是一个偏好问题,但第一个可能更可取。如果你不知道你提前删除的属性的名称,我只会使用第二个。
答案 4 :(得分:5)
就像getattr和setattr一样,只有在属性名称未知时才能使用delattr。
从这个意义上讲,它大致相当于几个python功能,这些功能用于访问比平时更低级别的内置功能,例如__import__
而不是import
和{{ 1}}而不是operator.add
答案 5 :(得分:3)
不确定内部工作方式,但从代码可重用性而不是混蛋同事的角度来看,使用del。来自其他语言的人也会更加清楚和理解。
答案 6 :(得分:1)
如果您认为delattr
更明确,那么为什么不一直使用getattr
而不是object.attr
?
至于引擎盖......你的猜测和我的一样好。如果没有明显好转。
答案 7 :(得分:1)
这是一个老问题,但我想把我的2美分投入。
虽然del foo.bar
更优雅,但有时您需要delattr(foo, "bar")
。比如,如果您有一个交互式命令行界面,允许用户通过键入名称动态删除对象中的任何成员,那么您别无选择,只能使用后一种形式。