发出del语句时:
del var
不应该从已知变量列表中删除它,并且python解释器不应该吐出“未解析的引用”错误吗?
或者只是删除对象并保留名称(var)不指向任何地方?为什么这种行为会有用?在什么情况下?
此外,我只是在谈论删除单个变量。不是列出[3]或类似的。
注意:我在问这个python的行为是否意味着这样。在什么情况下,它仍然有用。
编辑:Charles Addis给出了详细的解释。我也承认我的错误,我将pycharm行为误认为官方python。我现在正在尝试ipython以及官方的python交互式shell。尽管这是我的错误,但我很高兴我学到了很多关于python变量以及一些python调试命令的信息。答案 0 :(得分:2)
不确定你在问什么,显然会发生什么......
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> x = 10
>>> 'x' in vars()
True
>>> vars()['x']
10
>>> del x
>>> 'x' in vars()
False
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
正如您所看到的,Python允许访问locals()
中当前范围内的有效标识符(vars()
同样有效 - 还有dir(obj)
将显示对象的属性) ...所以del实际上将它从内存中删除,从而将它从这些函数返回的数据结构中删除。因此标识符不再有效。它不像在C中那样可以释放一些内存并将值设置为NULL
。
>>> x = 10
>>> def func():
... global x
... del x
...
>>> x
10
>>> func()
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>>
我们将使用ID函数来证明这一点:
Help on built-in function id in module __builtin__:
id(...)
id(object) -> integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
注意这里发生的事情,你会发现对于不可变类型,不同的变量引用相同的内存(字符串在python中是不可变的并且是实例化的,这意味着每个唯一字符串只存储一个副本 - - 在红宝石中,符号是实习字符串。)
>>> import sys
>>> x = 10 # 10 is a common value, probably exists in memory already
>>> sys.getrefcount(x)
26
>>> id(x) # memory location of x
140266396760096
>>> y = x
>>> id(y) == id(x)
True
>>> z = 10
>>> id(z) == id(y) == id(x)
True
>>> sys.getrefcount(y)
28
>>> sys.getrefcount(z)
28
>>> del y, z
>>> sys.getrefcount(x)
26
>>> del x
>>> x = 'charlie'
>>> id(x)
4442795056
>>> y = 'charlie'
>>> z = x
>>> id(x) == id(y) == id(z)
True
>>> sys.getrefcount(x)
4
>>> sys.getrefcount(y)
4
>>> sys.getrefcount(z)
4
>>> del y
>>> del x
>>> sys.getrefcount(z) # will be two because this line is an additional reference
2
>>> id(z) # pay attention to this memory location because this
4442795056 # is the last remaining reference to 'charlie', and
>>> del z # when it goes out of scope 'charlie' is removed from
>>> # memory.
>>> id('charlie') # This has a different memory location because 'charlie'
4442795104 # had to be re-created.
首先我们设置标识符&#39; x&#39; == 10,一个常见的整数值。由于10是如此常见的值,它几乎可以保证进程内存中的某些东西已经具有该值。由于整数在python中是不可变的,我们只需要存储在内存中的每个唯一值的一个副本。在这种情况下,内存中有24个其他对10的引用。设置x = 10
会创建第25个引用,并且调用sys.getrefcount(x)
是第26个引用(尽管它很快超出范围)。当我们设置y = 10
和z = x
时,我们知道它们都指向相同的数据,因为它们都具有相同的内存位置。调用del
会改变引用计数,但即使删除了所有3个,整数10仍然存在于内存中。
接下来,我们创建集x = 'charlie'
,然后是y = 'charlie'
,最后是z = x
。您可以看到所有这些变量都具有相同的内存地址。删除所有这些变量后,不再有'charlie'
的引用。我们可以通过调用id('charlie')
来验证这一点,这将产生一个不同的内存地址,这意味着当我们调用该函数时,字符串在内存中不存在。
需要注意的另一件事是'charlie'
和10
在内存中的位置。 10
的内存地址明显高于查理。这是因为它们存在于不同的存储位置。堆上存在'charlie'
,而堆栈上存在10
。
>>> hex(id(10)) # high address, this is on the stack
'0x7f9250c0b820'
>>> hex(id('charlie')) # lower address, this is on the heap
'0x108cfac60
答案 1 :(得分:1)
不应该从已知变量列表中删除它,不应该删除它 python解释器吐出“未解析的引用”错误?
这正是发生的事情。在您del
之后,下一次引用它将会引发NameError
。
或者只是删除对象并保留名称(var) 不指向任何地方?为什么这种行为会有用?在 什么情况?
在Python中,事情有点不同。您可能习惯使用其他语言的“变量”。
存在数据存在的对象空间 - 以及名称所在的命名空间。
names 是我们通常在其他语言中称为变量的东西,但在Python中它们只是数据空间中对象的标签。
使用del
删除标签(名称)后,它只会删除指向该对象的标签。对象(具有值)仍然存在;除非它没有被任何其他名称引用,在这种情况下,Python将垃圾收集它。名称只是指向对象空间中对象的轻量级标签,是我们访问这些对象的唯一方式。
以下是一个例子来说明这一点:
>>> x = 5
>>> y = x
>>> del x
>>> y
5
现在我删除了x
,但由于y
仍然指向与x
相同的对象(整数5
),它仍然存在,我可以再次访问它;但如果我尝试访问x
:
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
答案 2 :(得分:1)
“del”从当前名称空间中删除名称。如果底层对象的引用计数降为零,则释放对象本身。
>>> import sys
>>> x = 123456
>>> y = x # create a second reference to the number
>>> dir() # known variables include "x" and "y"
['__builtins__', '__doc__', '__name__', '__package__', 'sys', 'x', 'y']
>>> sys.getrefcount(x)
3
>>> del x # remove "x" as a known variable
>>> dir() # known variables includes only "y"
['__builtins__', '__doc__', '__name__', '__package__', 'sys', 'y']
>>> sys.getrefcount(y) # reference count is now lower by 1
2
>>> del y # remove "y" as a known variable
>>> dir() # known variables no longer include "x" and "y"
['__builtins__', '__doc__', '__name__', '__package__', 'sys']
>>> x # unresolved variable raises a "NameError"
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
x # unresolved variable raises a "NameError"
NameError: name 'x' is not defined