212

这可能很愚蠢,但它已经在我的大脑后面唠叨了一段时间。

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

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

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

4

8 回答 8

305

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

这意味着第一次运行的速度快(但差别不大——在我的机器上为 0.15 μs)。

就像其他人所说的那样,当您要删除的属性是动态确定的时,您真的应该只使用第二种形式。

[编辑显示函数内部生成的字节码指令,编译器可以在其中使用LOAD_FASTLOAD_GLOBAL]

于 2009-07-13T17:58:51.470 回答
45
  • 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来做。

于 2013-10-15T11:49:04.253 回答
18

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

于 2009-07-13T17:55:06.437 回答
15

这确实是一个偏好问题,但第一个可能更可取。如果您不知道要提前删除的属性的名称,我只会使用第二个。

于 2009-07-13T17:34:59.410 回答
5

就像 getattr 和 setattr 一样,delattr 只能在属性名称未知时使用。

从这个意义上说,它大致相当于用于访问比您通常可用的更低级别的内置功能的几个 python 功能,例如__import__代替importoperator.add代替+

于 2009-07-13T18:00:48.610 回答
3

不确定内部工作原理,但从代码可重用性和不要成为混蛋同事的角度来看,使用 del。来自其他语言的人也更清楚和理解。

于 2009-07-13T18:03:59.603 回答
1

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

至于引擎盖下......你的猜测和我的一样好。如果不是明显更好。

于 2009-07-13T17:59:44.680 回答
1

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

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

于 2014-07-08T11:23:29.227 回答