Answers:
首先,除了局部变量,您还可以进行其他操作
del list_item[4]
del dictionary["alpha"]
两者都应该明显有用。其次,del
在局部变量上使用可使意图更清晰。相比:
del foo
至
foo = None
我知道在这种情况下del foo
,目的是从范围中删除变量。目前尚不清楚这样foo = None
做。如果有人刚分配,foo = None
我可能认为这是无效代码。但是我立即知道某个编码人员del foo
正在尝试做什么。
del
过在内存密集型计算中使用过,但是当我看到它时,我立即意识到了为什么这样做是必要的。
del
意图信号(因为注释可以在不增加语言的情况下也可以做到),但是我认为这是最好的答案。
len()
以相同的方式质疑该功能。如果是这种情况,则可能出于意见或口味的考虑关闭了该请求。Python只是倾向于为基本操作提供原语,而不是依赖方法。
这是做什么的一部分del
(来自Python语言参考):
删除名称会从本地或全局名称空间中删除该名称的绑定
分配None
名称不会从名称空间中删除名称的绑定。
(我想可能存在一些关于删除名称绑定是否真正有用的争论,但这是另一个问题。)
del
删除他建议分配的名称绑定None
的替代方法。
NameError
。格雷格·休吉尔(Greg Hewgill)非常区分。正是这种区别使您对海报“清楚地”理解的内容的主张对我来说还不清楚。
我发现一个del
有用的地方是清理for循环中的无关变量:
for x in some_list:
do(x)
del x
现在,您可以确定,如果在for循环之外使用x,它将是未定义的。
del
行是否应该缩进(即循环的一部分)?
NameError: name 'x' is not defined
如果列表为空,则将导致此问题。
用删除变量名del
可能很少使用,但是如果没有关键字就无法轻易实现。如果您可以通过编写来创建变量名a=1
,那么理论上可以通过删除a来撤消该操作。
在某些情况下,它可以简化调试过程,因为尝试访问已删除的变量将引发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")
如果您选择向类实例动态添加属性,那么您当然希望能够通过编写来撤消它
del a.a
有一个特定的示例说明您在检查异常时应使用的时间del
(可能还有其他,但我知道这是sys.exc_info()
一时的事)。此函数返回一个元组,引发的异常类型,消息和回溯。
前两个值通常足以诊断错误并采取措施,但第三个值包含引发异常与捕获异常之间的整个调用堆栈。特别是如果您做类似的事情
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 x
x
指示的定义r -> o
(r
指向对象的引用o
),但del x
更改r
而不是o
。这是对对象(而不是与关联的对象)的引用(指针)的操作x
。区分r
和o
是此处的关键。
locals()
。globals()
如果x
属于它,将其删除。x
属于的地方,而不影响x
指向的地方。内存中唯一的物理更改是这样。例如,如果x
在字典或列表中,则将其(作为参考)从那里(不一定从对象池中)删除。在此示例中,它所属的字典是locals()
与重叠的堆栈框架()globals()
。使用numpy.load后强制关闭文件:
利基用法也许,但我发现它在numpy.load
用于读取文件时很有用。我会不时地更新文件,并且需要将具有相同名称的文件复制到目录中。
我曾经del
发布过文件,并允许我复制到新文件中。
请注意,我想避免使用with
上下文管理器,因为我在命令行上玩弄图并且不想太多地按下Tab键!
看到这个问题。
__del__()
垃圾对象的方法被调用,甚至如果它被调用的。因此,除了希望__del__()
某种方法(在对象成为垃圾之后不久)被调用的方法外,没有其他方法释放资源的API 在某种程度上被破坏了。
del
通常在__init__.py
文件中看到。__init__.py
文件中定义的所有全局变量都将自动“导出”(将包含在中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
可用于,我觉得有用我的情况是这样的:
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'
这两个功能都可以在不同的封装/模块和程序员不需要知道默认值参数c
在f
实际拥有。因此,通过将kwargs与del结合使用,可以通过将其设置为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
并希望删除目录中的元素,这可能会很有用。不过,我认为关键字对此无济于事,因为一个人只能制作一个[].remove(index)
方法(该.remove
方法实际上是搜索并删除第一个实例值)。
[].pop(index)
和[].remove(item)
。"index"
在谈论价值时不要使用named变量,这会使它看起来很混乱。
del
当使用Numpy处理大数据时,我发现对于伪手动内存管理很有用。例如:
for image_name in large_image_set:
large_image = io.imread(image_name)
height, width, depth = large_image.shape
large_mask = np.all(large_image == <some_condition>)
# Clear memory, make space
del large_image; gc.collect()
large_processed_image = np.zeros((height, width, depth))
large_processed_image[large_mask] = (new_value)
io.imsave("processed_image.png", large_processed_image)
# Clear memory, make space
del large_mask, large_processed_image; gc.collect()
这可能是由于Python GC无法跟上系统疯狂地交换脚本而使脚本陷入停顿状态,并且在松散的内存阈值下它可以完美平滑地运行,从而留出了很大的可用空间来浏览机器和代码,而它的工作。
我想详细说明可接受的答案,以突出显示将变量设置为None
与使用删除变量之间的细微差别del
:
给定变量foo = 'bar'
,并提供以下函数定义:
def test_var(var):
if var:
print('variable tested true')
else:
print('variable tested false')
最初声明后,test_var(foo)
产量将variable tested true
达到预期。
现在尝试:
foo = None
test_var(foo)
产生variable tested false
。
将此行为与:
del foo
test_var(foo)
现在提高了NameError: name 'foo' is not defined
。
又一小生用法:在pyroot与ROOT5或ROOT6,“删除”可以是,以去除被称为无再现有C ++对象Python对象是有用的。这允许pyroot的动态查找来找到一个同名的C ++对象,并将其绑定到python名称。因此,您可能会遇到以下情况:
import ROOT as R
input_file = R.TFile('inputs/___my_file_name___.root')
tree = input_file.Get('r')
tree.Draw('hy>>hh(10,0,5)')
R.gPad.Close()
R.hy # shows that hy is still available. It can even be redrawn at this stage.
tree.Draw('hy>>hh(3,0,3)') # overwrites the C++ object in ROOT's namespace
R.hy # shows that R.hy is None, since the C++ object it pointed to is gone
del R.hy
R.hy # now finds the new C++ object
希望此利基市场将通过ROOT7的精明对象管理而关闭。
一旦我不得不使用:
del serial
serial = None
因为仅使用:
serial = None
释放串口的速度不够快,无法立即再次打开它。从那堂课中,我学到了del
真正的意思:“现在就GC!等到完成为止”,这在很多情况下非常有用。当然,您可能会有一个system.gc.del_this_and_wait_balbalbalba(obj)
。
__del__()
在Python中依靠GC并调用总是错误的(尽管我不知道这种设计的原因),最好使用上下文管理器API(该with
语句)。
serial
模块还可以与Jython一起使用,因此您的hack在那里不起作用!
del在许多语言中都等同于“未设置”,并且作为从另一种语言到python的交叉参考点。人们倾向于寻找命令,它们执行的操作与以前使用第一语言时所做的相同……将var更改为“”或没有任何操作并不会真正从范围中删除该var。它只是清空其值,该var本身的名称仍将存储在内存中...为什么?!在占用大量内存的脚本中..保持垃圾桶的“否”和“反之……”每种语言都具有某种形式的“未设置/删除” var函数..为什么不使用python?
del
调用垃圾回收器的速度不会比快= None
,或者从长远来看也不会留下垃圾。您可能想了解Python的垃圾回收。
python中的每个对象都有一个标识符,类型,与之关联的引用计数,当我们使用del时,引用计数会减少,当引用计数变为零时,它很可能成为垃圾回收的候选对象。与将标识符设置为“无”相比,这可以区分del。在后面的情况下,它只是意味着该对象被遗忘了(直到我们超出范围,在这种情况下,计数减少了),现在标识符仅指向其他某个对象(内存位置)。
del
。