什么时候del在python中有用?

我真的不知道为什么python需要del关键字(大多数语言似乎没有类似的关键字)。 例如,不是删除一个variables,而是可以将None赋值给它。 从字典中删除时,可以添加一个del方法。

有没有任何理由保持python的del ,或者它是Python的预垃圾回收日的遗迹?

首先,除了局部variables,你还可以删除其他东西

 del list_item[4] del dictionary["alpha"] 

这两者都应该是明显有用的。 其次,在局部variables上使用del使得intent更加清晰。 比较:

  del foo 

  foo = None 

我知道在del foo的情况下,意图是从范围中删除variables。 目前尚不清楚foo = None是否正在这样做。 如果有人刚分配foo = None我可能会认为这是死代码。 但是,我立即知道代码del foo有人想要做什么。

这是del的一部分(来自Python语言参考 ):

删除名称将删除该名称与本地或全局名称空间的绑定

None分配给名称不会从命名空间中删除该名称的绑定。

(我想可能会有一些关于删除名称绑定是否有用的争论,但这是另一个问题。)

我发现del有用的一个地方是清除for循环中的无关variables:

 for x in some_list: do(x) del x 

现在你可以确定,如果你在for循环之外使用x,x将是未定义的。

只是另一个想法。

当像Django一样在框架中debugginghttp应用程序时,调用堆栈中充满了以前使用的无用和混乱的variables,特别是当它是一个很长的列表时,对于开发人员来说可能是非常痛苦的。 所以,在这一点上,命名空间控制可能是有用的。

当你使用sys.exc_info()来检查一个exception的时候,有一个特别的例子,你应该使用del (也许还有其他的,但是我知道这个关于这个)。 这个函数返回一个元组,引发的exceptiontypes,消息和回溯。

前两个值通常足以诊断错误并对其执行操作,但是第三个值包含引发exception的位置和exception被捕获的位置之间的整个调用堆栈。 特别是,如果你做类似的事情

 try: do_evil() except: exc_type, exc_value, tb = sys.exc_info() if something(exc_value): raise 

回溯, tb结束于调用堆栈的本地,创build一个不能被垃圾回收的循环引用。 因此,做这件事很重要:

 try: do_evil() except: exc_type, exc_value, tb = sys.exc_info() del tb if something(exc_value): raise 

打破循环引用。 在许多情况下,如果想要调用sys.exc_info() ,就像元类魔术一样,回溯有用的,所以在可能离开exception处理程序之前,必须确保清除它。 如果你不需要回溯,你应该立即删除,或者只是:

 exc_type, exc_value = sys.exc_info()[:2] 

一起避免它。

使用numpy.load后强制closures文件:

也许一个利基的用法,但我发现它使用numpy.load读取文件时很有用。 每过一段时间,我都会更新文件,并需要将同名的文件复制到目录中。

我用del释放文件,并允许我复制新文件。

注意我想避免with上下文pipe理器,因为我在命令行中使用图标,并且不想按Tab键很多!

看到这个问题。

明确使用“del”也比将一个variables赋值给None更好。 如果你试图删除一个不存在的variables,你会得到一个运行时错误,但是如果你尝试设置一个不存在的variables,Python会默默地将一个新的variables设置为None,想要删除它在哪里。 所以德尔会帮助你早点发现你的错误

为以上答案添加几点: del x

x的定义表示r – > o(指向对象o的引用r),但del x改变r而不是o。 它是对对象的引用(指针)的操作,而不是与x关联的对象。 区分r和o是关键。

  • 它从locals()
  • 如果它属于那里,则将其从globals()移除。
  • 将其从堆栈帧中删除(从物理上删除引用,但对象本身驻留在对象池中而不是堆栈帧中)。
  • 将其从当前范围中删除。 限制局部variables的定义范围是非常有用的,否则会导致问题。
  • 更多的是关于名称的声明而不是内容的定义。
  • 它影响x所属的位置,而不是x指向的位置。 记忆中唯一的物理变化就是这个。 例如,如果x位于字典或列表中,则它(作为引用)将从此处(而不一定是来自对象池)中删除。 在这个例子中,它所属的字典是堆栈框架( locals() ),它与globals()重叠。

删除variables与将其设置为None不同

del删除variables名可能是很less用到的东西,但是如果没有关键字就不能实现。 如果你可以通过写a=1来创build一个variables名,那么理论上你可以通过删除一个来取消它。

在某些情况下,它可以使debugging更容易,因为试图访问已删除的variables会引发NameError。

您可以删除类实例属性

Python可以让你写下如下的东西:

 class A(object): def set_a(self, a): self.a=a a=A() a.set_a(3) if hasattr(a, "a"): print("Hallo") 

如果您selectdynamic地将属性添加到类实例,您当然希望能够通过写入来撤消它

 del aa 

我认为del有它自己的语法的原因之一是,用函数replace它可能在某些情况下是困难的,因为它在绑定或variables上运行,而不是它引用的值。 因此,如果要创build一个函数版本的del,则需要传入一个上下文。del foo需要成为globals()。remove('foo')或locals()。remove('foo')并且可读性较差。 不过,我认为摆脱德尔将是好的,因为它看似罕见的用途。 但是消除语言特征/缺陷可能是痛苦的。 也许蟒4将删除它:)

作为 del可以使用的一个例子 ,我觉得这很有用,我喜欢这样的情况:

 def f(a, b, c=3): return '{} {} {}'.format(a, b, c) def g(**kwargs): if 'c' in kwargs and kwargs['c'] is None: del kwargs['c'] return f(**kwargs) # g(a=1, b=2, c=None) === '1 2 3' # g(a=1, b=2) === '1 2 3' # g(a=1, b=2, c=4) === '1 2 4' 

这两个函数可以在不同的包/模块中,程序员不需要知道f实际具有的默认值参数c 。 所以通过与del组合使用kwargs,可以通过将它设置为None(或者在这种情况下,也可以放弃它)来说“我想要c上的默认值”。

你可以用类似的方法做同样的事情:

 def g(a, b, c=None): kwargs = {'a': a, 'b': b} if c is not None: kwargs['c'] = c return f(**kwargs) 

不过,我发现前面的例子更干燥优雅。

什么时候del在python中有用?

您可以使用它来移除数组中的单个元素,而不是切片语法x[i:i+1]=[] 。 这可能是有用的,例如,如果你在os.walk并希望删除目录中的元素。 我不会考虑一个有用的关键字,因为我们可以创build一个[].remove(index)方法( .remove方法实际上是search-and-remove-first-instance-value)。

del__init__.py文件中经常出现。 任何在__init__.py文件中定义的全局variables都会被自动“导出”(它将被包含在from module import * )。 避免这种情况的一种方法是定义__all__ ,但这会变得混乱,而不是每个人都使用它。

例如,如果你在__init__.py类似的代码

 import sys if sys.version_info < (3,): print("Python 2 not supported") 

然后你的模块会导出sys名称。 你应该写

 import sys if sys.version_info < (3,): print("Python 2 not supported") del sys 

一旦我不得不使用:

 del serial serial = None 

因为只使用:

 serial = None 

没有足够快地释放串口来立即打开它。 从这一课我学到了del真正含义:“GC now!”并等到它完成了,这在很多情况下都是非常有用的。 当然,你可能有一个system.gc.del_this_and_wait_balbalbalba(obj)

del在许多语言中相当于“unset”,并且是从另一种语言转换为python的交叉参考点。人们倾向于寻找与他们的第一语言完全相同的命令…也设置var“”或者none都不能真正的将var从范围中删除,只是清空它的值,var本身的名字仍然会被存储在内存中…为什么?!? 在一个内存密集的脚本..保持垃圾背后它只是一个不,无论如何…每种语言都有一些“unset /删除”var函数的forms..为什么不是python?

python中的每个对象都有一个标识符,types,引用计数,当我们使用del时,引用计数减less,当引用计数变为零时,它是一个潜在的垃圾收集候选者。 与将标识符设置为None相比,这区分了del。 在后面的例子中,它只是意味着对象被忽略(直到我们超出了范围,在这种情况下计数减less),现在标识符指向其他对象(内存位置)。