gpt4 book ai didi

python - 在 Python 中,为什么 'y = x; y += 1' 不增加 x?

转载 作者:太空宇宙 更新时间:2023-11-04 10:29:59 25 4
gpt4 key购买 nike

首先创建一个显示引用计数的函数(注意我们必须每次都-1才能得到正确的值,因为函数本身是INCREF-s参数)

>>> from sys import getrefcount as rc
>>> x=1.1
>>> rc(x)-1
1

现在对同一个 PyObject 进行另一个引用:

>>> y=x

>>> rc(x)-1
2
>>> rc(y)-1
2

>>> x is y
True

现在对第二个句柄 y 执行操作:

>>> y+=1

这应该在 y 指向的 PyObject 上调用 PyNumber_InPlaceAdd

所以如果这是真的,我希望 x 也能读取 2.1

>>> x,y
(1.1, 2.1)

>>> x is y
False

>>> rc(x)-1
1
>>> rc(y)-1
1

所以我的问题是,Python 在内部做了什么来提供正确的行为,而不是我从查看 PyNumber_InPlaceAdd 时期望的行为?

(注意:我使用的是 1.1;如果我使用 1,则初始引用计数将 >300,因为必须使用 1在 CPython 的幕后无处不在,它足够聪明地重用对象。)

(这也引出了一个问题:如果我有 foo = 20; bar = 19; bar += 1 这是否意味着它必须查看所有对象并检查是否有已经存在一个具有这个值的对象,如果重用它呢?一个简单的测试表明答案是否定的。这是个好消息。一旦程序变大,它就会非常慢。所以 Python 必须只针对小整数进行优化。 )

最佳答案

为此你不需要getrefcount,你可以只使用id :

>>> x = 1.1
>>> id(x)
50107888
>>> y = x
>>> id(y)
50107888 # same object
>>> y += 1
>>> id(y)
40186896 # different object
>>> id(x)
50107888 # no change there

float 对象(连同例如 strint)在 Python 中是不可变的,它们不能被改变到位。因此,加法操作创建一个新对象,具有新值,并将其分配给名称 y,有效地:

temp = y + 1
y = temp

在 CPython 中,从 -5256 的整数是“内部的”,即存储以供重用,这样任何对结果的操作,例如1 将提供对同一对象 的引用。与每次需要时为这些常用值创建新对象相比,这可以节省内存。你是对的,每次可能需要一个新对象时,搜索所有现有对象进行匹配是一件很痛苦的事情,所以这只能在有限的范围内完成。使用连续范围还意味着“搜索”实际上只是数组中的一个偏移量。

关于python - 在 Python 中,为什么 'y = x; y += 1' 不增加 x?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27399340/

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