gpt4 book ai didi

python (deI) 语句和 python 行为

转载 作者:太空狗 更新时间:2023-10-30 02:56:14 25 4
gpt4 key购买 nike

发出 del 语句时:

del var

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

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

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

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

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

最佳答案

不确定你在问什么,因为很明显这就是发生的事情......

>>> 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 时才被释放,他提出了一个很好的观点。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 中是不可变的并且是 interned 的,这意味着每个唯一字符串只存储一个副本 - 在 ruby ,符号是内部字符串)。

>>> 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.

首先我们设置标识符 'x' == 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。这是因为它们存在于不同的内存位置。 'charlie' 存在于堆上,而 10 存在于堆栈上。

>>> hex(id(10))         # high address, this is on the stack
'0x7f9250c0b820'
>>> hex(id('charlie')) # lower address, this is on the heap
'0x108cfac60

关于python (deI) 语句和 python 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40099427/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com