我真的想不出Python需要del关键字的任何原因(而且大多数语言似乎都没有类似的关键字)。例如,与其删除变量,还不如将None赋值给它。当从字典中删除时,可以添加del方法。
在Python中保留del是有原因的吗,还是它是Python前垃圾收集时代的遗迹?
我真的想不出Python需要del关键字的任何原因(而且大多数语言似乎都没有类似的关键字)。例如,与其删除变量,还不如将None赋值给它。当从字典中删除时,可以添加del方法。
在Python中保留del是有原因的吗,还是它是Python前垃圾收集时代的遗迹?
当前回答
当你使用sys.exc_info()检查异常时,有一个特定的例子说明你应该使用del(可能还有其他的例子,但我知道这个是现成的)。这个函数返回一个元组、引发的异常类型、消息和一个回溯。
前两个值通常足以诊断错误并对其进行处理,但第三个值包含从引发异常的位置到捕获异常的位置之间的整个调用堆栈。特别是,如果你做
try:
do_evil()
except:
exc_type, exc_value, tb = sys.exc_info()
if something(exc_value):
raise
回溯,TB最终在调用堆栈的局部变量中,创建了一个不能被垃圾收集的循环引用。因此,重要的是要做到:
try:
do_evil()
except:
exc_type, exc_value, tb = sys.exc_info()
del tb
if something(exc_value):
raise
打破循环引用。在许多情况下,您希望调用sys.exc_info(),就像使用元类魔法一样,回溯是有用的,因此您必须确保在可能离开异常处理程序之前清除它。如果你不需要回溯,你应该立即删除它,或者直接执行:
exc_type, exc_value = sys.exc_info()[:2]
一起避免这一切。
其他回答
作为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实际上有什么默认值。因此,通过将kwargs与del结合使用,您可以将其设置为None(或者在这种情况下也可以保留它),从而说“I want the default value on c”。
你也可以这样做:
def g(a, b, c=None):
kwargs = {'a': a,
'b': b}
if c is not None:
kwargs['c'] = c
return f(**kwargs)
然而,我发现前面的例子更加DRY和优雅。
Del经常出现在__init__.py文件中。任何在__init__.py文件中定义的全局变量都将自动“导出”(它将包含在from模块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
由于我还没有看到交互式控制台的答案,我将展示一个。
当foo=None时,该引用和对象存在,它不指向它。
而del foo也会销毁对象和引用。
如果你这样做如果foo是None并且它被删除了它就会升起NameError作为引用,它的对象所有介于两者之间的东西都会被del删除
删除目标列表会递归地从左到右删除每个目标。
与此同时,foo=None只是一个指向None的引用,因此引用仍然是有效的,对象也是如此。
[…在Python中,变量是对象的引用,任何变量都可以引用任何对象[…]
链接到引用1
链接到引用2
显式使用"del"也是比将变量赋值为None更好的实践。如果你试图删除一个不存在的变量,你会得到一个运行时错误,但如果你试图将一个不存在的变量设置为None, Python会无声地将一个新变量设置为None,让你想要删除的变量留在原来的位置。所以del会帮助你尽早发现错误
首先,你可以删除除局部变量之外的其他东西
del list_item[4]
del dictionary["alpha"]
这两者显然都是有用的。其次,在局部变量上使用del使意图更加明确。比较:
del foo
to
foo = None
我知道在del foo的情况下,目的是从作用域中删除变量。foo = None是否这样做还不清楚。如果有人只是赋值foo = None,我可能会认为这是死代码。但我立刻就知道,编码del foo的人想要做什么。