不确定你在问什么,因为很明显那就是发生的事情...
>>> 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
>>>
更新:
当Raymond提到对象本身(即指针指向的实际内存数据,缺乏更详细的解释)只有在引用计数为0时才会被释放时,他提出了一个很好的观点。在我看来,他可以在python解释器中更好地详细说明这一点,所以我来试试。
我们将使用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中,字符串是不可变的并且被内部化,这意味着每个唯一字符串只存储一份副本 - 在Ruby中,符号是内部化的字符串)。
>>> import sys
>>> x = 10
>>> sys.getrefcount(x)
26
>>> id(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)
2
>>> id(z)
4442795056
>>> del z
>>>
>>> id('charlie')
4442795104
首先,我们将标识符“x”设置为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'
更高的内存地址。这是因为它们存在于内存的不同位置。'charlie'
存在于堆上,而10
存在于栈上。
>>> hex(id(10))
'0x7f9250c0b820'
>>> hex(id('charlie'))
'0x108cfac60
del var;var
,那么就会发生这种情况。你期望del var
尝试返回已删除的变量吗? - Mark RansomNameError
或UnboundLocalError
异常。一旦执行del var
,var
的本地名称就消失了。如果其他名称引用了相同的对象,则该对象仍将存在,只是不再使用该名称。 - ShadowRanger