gpt4 book ai didi

python - 困惑为什么在第二次评估不可变字符串的 += 运算符后不会更改 Python3 中的 id

转载 作者:行者123 更新时间:2023-12-03 13:56:36 25 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Why is the id of a Python class not unique when called quickly?

(6 个回答)



Immutability in Python [duplicate]

(2 个回答)


1年前关闭。




我正在使用 Python 3.8.3 并且在检查字符串的 id 时得到了一些意想不到的输出,如下所示。

>>> a="d"
>>> id(a)
1984988052656
>>> a+="e"
>>> id(a)
1985027888368
>>> a+="h"
>>> id(a)
1985027888368
>>> a+="i"
>>> id(a)
1985027888368
>>>
在将“h”添加到 a 的行之后,id(a) 没有改变。当字符串不可变时,这怎么可能?
当我使用 a=a+"h"而不是 a+="h"并在 .py 文件中运行此代码时,我得到了相同的输出(我提到过,因为在某些情况下我们可以在 shell 中运行时看到不同的输出并在保存到文件后运行相同的代码)

最佳答案

这仅是由于在字节码评估循环中对字符串连接进行了奇怪的、略微粗略的优化。 INPLACE_ADD 实现特殊情况下的两个字符串对象:

case TARGET(INPLACE_ADD): {
PyObject *right = POP();
PyObject *left = TOP();
PyObject *sum;
if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) {
sum = unicode_concatenate(tstate, left, right, f, next_instr);
/* unicode_concatenate consumed the ref to left */
}
else {
...
并调用 unicode_concatenate 委托(delegate)给 PyUnicode_Append 的助手,它试图就地改变原始字符串:
void
PyUnicode_Append(PyObject **p_left, PyObject *right)
{
...
if (unicode_modifiable(left)
&& PyUnicode_CheckExact(right)
&& PyUnicode_KIND(right) <= PyUnicode_KIND(left)
/* Don't resize for ascii += latin1. Convert ascii to latin1 requires
to change the structure size, but characters are stored just after
the structure, and so it requires to move all characters which is
not so different than duplicating the string. */
&& !(PyUnicode_IS_ASCII(left) && !PyUnicode_IS_ASCII(right)))
{
/* append inplace */
if (unicode_resize(p_left, new_len) != 0)
goto error;

/* copy 'right' into the newly allocated area of 'left' */
_PyUnicode_FastCopyCharacters(*p_left, left_len, right, 0, right_len);
}
...
优化仅在 unicode_concatenate 时发生可以保证没有其他对 LHS 的引用。您的初始 a="d"有其他引用,因为 Python 使用 Latin-1 范围内的 1 字符字符串的缓存,所以优化没有触发。在其他一些情况下,优化也可能无法触发,例如 LHS 有缓存的哈希,或者 realloc需要移动字符串(在这种情况下,大多数优化的代码路径都会执行,但它不会成功执行就地操作)。

这种优化违反了 id 的正常规则。和 += .通常情况下, +=在不可变对象(immutable对象)上应该在清除对旧对象的引用之前创建一个新对象,所以新旧对象应该有重叠的生命周期,禁止等于 id值(value)观。优化到位后, += 之后的字符串与 += 之前的字符串具有相同的 ID .
语言开发人员认为他们更关心那些将字符串连接置于循环中、看到性能不佳并认为 Python 很糟糕的人,而不是他们关心这个晦涩的技术点。

关于python - 困惑为什么在第二次评估不可变字符串的 += 运算符后不会更改 Python3 中的 id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62621386/

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