在python,del或delattr中哪个更好?


179

这可能很愚蠢,但已经困扰了我一段时间。

Python提供了两种从对象中删除属性的内置方法,即del命令字和delattr内置函数。我更喜欢delattr,因为我认为它更加明确:

del foo.bar
delattr(foo, "bar")

但是我想知道它们之间是否存在内在差异。

Answers:


264

第一个比第二个更有效。 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_FASTLOAD_GLOBAL


6
您使用什么工具生成了这个?
三联画

33
dis模块。您可以使用python -m dis并输入一些代码从命令行运行它,或者使用来反汇编函数dis.dis()
英里

15
过早的优化是万恶之源。;-)但是,是的,您当然是对的。
Lennart Regebro

26
..so那么,对金钱的热爱是过早的优化吗?
John Fouhy

5
过早的优化是对金钱的热爱的一个子集,因为这意味着您正在尝试减少处理能力上的花费:)
Rob Grant

41
  • del更明确,更有效;
  • delattr允许删除动态属性。

请考虑以下示例:

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
您可以使用del做第二个。del self.__dict__[name],当然假设元类没有有趣的事情
smac89 '18

17

无疑是前者。在我看来,这就像在询问是否foo.bar比更好getattr(foo, "bar"),而且我认为没有人在问这个问题:)


3
我确定至少有一个人比foo.bar更喜欢getattr(foo,“ bar”)。当然,我不会同意他们的观点。但是,一个人仍然足以使其毫无疑问地成为前者。
杰森·贝克

3
@Jason然后,通过对短语的解释,没有什么比其他任何“无疑地更好”。我认为这是“毫无疑问”的完全合理的用法。
Phob

26
如果有可能该属性不存在,并且您希望设置默认值而不必编写try / except块,则最好使用getattr。即。gettattr(foo,“ bar”,None)
马克·吉本斯

2
@MarcGibbons:等等,这件事吗?我一直使用这种模式if hasattr(obj, 'var') and obj.var == ...... if getattr(obj, 'var', None) == ...在大多数情况下,我可以将其简化为!我认为,它略短且易于阅读。
ArtOfWarfare 2015年

@ArtOfWarfare hasattr实际上致电getattr
cheniel

14

这实际上是一个优先事项,但第一个可能更可取。如果您不知道要提前删除的属性的名称,我只会使用第二个。


5

就像getattr和setattr一样,仅当属性名称未知时才应使用delattr。

从这个意义上讲,它大致等同于几个python功能,这些功能用于以比通常可用的级别低的级别访问内置功能,例如,__import__代替importoperator.add代替+


3

不确定内部工作原理,但是从代码的可重用性出发,并且不要太讨厌同事,请使用del。来自其他语言的人也更加清楚和理解。


1

如果您认为delattr更明确,那为什么不一直使用getattr而不是object.attr

至于幕后...你的猜测和我的一样好。如果没有明显好转。


1

这是一个古老的问题,但是我想投入2美分。

虽然del foo.bar更优雅,但有时​​您会需要delattr(foo, "bar")。假设,如果您有一个交互式命令行界面,该界面允许用户通过键入name动态删除对象中的任何成员,那么您别无选择,只能使用后者的形式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.