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

pyd*_*nny 166 python del

这可能是愚蠢的,但它一直在唠叨我的脑后.

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

del foo.bar
delattr(foo, "bar")
Run Code Online (Sandbox Code Playgroud)

但我想知道他们之间是否存在引擎盖下的差异.

Mil*_*les 252

第一个比第二个更有效. del foo.bar编译为两个字节码指令:

  2           0 LOAD_FAST                0 (foo)
              3 DELETE_ATTR              0 (bar)
Run Code Online (Sandbox Code Playgroud)

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             
Run Code Online (Sandbox Code Playgroud)

这转化为第一次运行快(但它不是一个巨大的差异 - 在我的机器上.15μs).

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

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

  • `dis`模块.您可以使用`python -m dis`从命令行运行它并键入一些代码,或者使用`dis.dis()`反汇编函数. (30认同)
  • 那么,对金钱的热爱是不成熟的优化呢? (25认同)
  • 过早优化是万恶之源.;-)但是,是的,你当然是对的. (15认同)
  • 你用什么工具来产生这个? (5认同)
  • 过早优化是对金钱的热爱的一个子集,因为这意味着你正在努力减少处理能力:) (5认同)
  • 我认为重要的是要注意没有Python程序,其中150 ns将以任何方式显着,因此两种方法之间的"效率差异"时间不应该是使用的决定因素.相反,可读性以及是否需要传递字符串应该是决定因素. (3认同)

Ole*_*rov 37

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

请考虑以下示例:

for name in ATTRIBUTES:
    delattr(obj, name)
Run Code Online (Sandbox Code Playgroud)

要么:

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)
Run Code Online (Sandbox Code Playgroud)

del不能这样做.

  • 您可以使用del做第二个。del self .__ dict __ [name]`,当然假设元类没有有趣的事情 (2认同)

Ale*_*nor 17

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

  • 当有可能该属性不存在并且您希望设置默认值而不必编写try/except块时,getattr是首选.即.gettattr(foo,"bar",无) (24认同)
  • 我敢肯定,至少*一个*人在foo.bar上更喜欢getattr(foo,"bar").当然,我不同意他们的看法.但是那个人仍然足以让毫无疑问成为前者. (3认同)
  • @Jason然后,通过你对这句话的解释,没有什么比其他任何东西"无疑更好"了.我认为这是"毫无疑问"的合理使用. (3认同)
  • @MarcGibbons:等等,这是一回事?我一直使用模式`if hasattr(obj, 'var') 和 obj.var == ...`...我可以将其简化为,`if getattr(obj, 'var', None) = = ...` 在大多数情况下!我认为更短更容易阅读。 (2认同)

Jas*_*ker 14

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


Alg*_*ias 5

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

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