我真的想不出Python需要del关键字的任何原因(而且大多数语言似乎都没有类似的关键字)。例如,与其删除变量,还不如将None赋值给它。当从字典中删除时,可以添加del方法。

在Python中保留del是有原因的吗,还是它是Python前垃圾收集时代的遗迹?


当前回答

这是我贡献的2美分:

我有一个优化问题,我使用一个Nlopt库。 我初始化类和它的一些方法,我在代码的其他几个部分使用。

我得到的结果是随机的,即使是同样的数值问题。

我刚刚意识到,通过这样做,一些虚假数据包含在对象中,而它应该没有任何问题。使用del后,我猜内存被正确地清除,这可能是一个内部问题的类,其中一些变量可能不喜欢被重用没有适当的构造函数。

其他回答

作为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和优雅。

另一个小众案例,但很有用。

from getpass import getpass

pass = getpass()
token = get_auth_token(pass)
del pass

# Assume more code here...

在删除pass变量之后,您不会冒它稍后被错误打印出来的风险,或者以其他方式结束在日志或堆栈跟踪中。

当你使用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 serial
serial = None

因为只使用:

serial = None

没有及时释放串口,无法立即再次打开。 从这一课中,我了解到del的真正意思是:“现在就开始!然后等待直到它完成”这在很多情况下都很有用。当然,你可能有一个system.gc.del_this_and_wait_balbalba (obj)。

除非重新初始化,否则Del将从当前作用域删除变量。将其设置为None将其保留在当前范围内。

a = "python string"        
print(a)
del a
print(a)
a = "new python string"
print(a)

输出:

python string
Traceback (most recent call last):
  File "testing.py", line 4, in <module>
    print(a)
NameError: name 'a' is not defined