python(deI)语句和python行为

时间:2016-10-18 04:17:58

标签: python

发出del语句时:

  

del var

不应该从已知变量列表中删除它,并且python解释器不应该吐出“未解析的引用”错误吗?

或者只是删除对象并保留名称(var)不指向任何地方?为什么这种行为会有用?在什么情况下?

此外,我只是在谈论删除单个变量。不是列出[3]或类似的。

注意:我在问这个python的行为是否意味着这样。在什么情况下,它仍然有用。

编辑:Charles Addis给出了详细的解释。我也承认我的错误,我将pycharm行为误认为官方python。我现在正在尝试ipython以及官方的python交互式shell。尽管这是我的错误,但我很高兴我学到了很多关于python变量以及一些python调试命令的信息。

3 个答案:

答案 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
>>>

更新

当Raymond提到对象本身时(读取:标识符所指向的内存中的实际数据,由于缺乏更详细的解释),只有当它的引用计数转到IMO他本可以在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中是不可变的并且是实例化的,这意味着每个唯一字符串只存储一个副本 - - 在红宝石中,符号是实习字符串。)

>>> 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 = 10z = 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