如果Python字符串是不可变的,为什么如果我使用+ =将其保留相同的ID?
Python中的字符串是不变的,这意味着该值无法更改。但是,在以下示例中附加到字符串时,看起来原始字符串内存已修改,因为ID保持不变:
>>> s = 'String'
>>> for i in range(5, 0, -1):
... s += str(i)
... print(f"{s:<11} stored at {id(s)}")
...
String5 stored at 139841228476848
String54 stored at 139841228476848
String543 stored at 139841228476848
String5432 stored at 139841228476848
String54321 stored at 139841228476848
相反,在下面的示例中,ID更改:
>>> a = "hello"
>>> id(a)
139841228475760
>>> a = "b" + a[1:]
>>> print(a)
bello
>>> id(a)
139841228475312
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于
str
恰好没有其他生活参考的情况,这是对CPYTHON特定的优化。在这种情况下,解释器“作弊”,允许其通过重新定位(可以放置,具体取决于堆布局)并直接附加数据来修改现有字符串,并经常在反复加压的环中大大降低工作(使其成为它)行为更像是摊销o(1)
附加list
而不是o(n)
每次复制操作)。除了不变的id
之外,它没有明显的效果在逻辑上被替换)。您实际上不应该依靠它(非参考计算口译员无法使用此技巧,因为他们不知道
str
是否具有其他参考),per pep8的第一个编程建议:如果您想打破优化,则有多种方法可以这样做,例如,将代码更改为:
通过创建别名,增加参考计数并告诉Python,将更改可见于
以外的某个地方可见。 s
,因此无法应用它。同样,代码类似:无法使用它,因为
s + a
首先发生,并且必须添加b
的临时性,而不是立即替换s
,优化太脆了,无法尝试处理。几乎相同的代码如:或:
通过确保最终串联始终是
s
是左操作数,并且结果用于立即替换s
来恢复优化。It's a CPython-specific optimization for the case when the
str
being appended to happens to have no other living references. The interpreter "cheats" in this case, allowing it to modify the existing string by reallocating (which can be in place, depending on heap layout) and appending the data directly, and often reducing the work significantly in loops that repeatedly concatenate (making it behave more like the amortizedO(1)
appends of alist
rather thanO(n)
copy operations each time). It has no visible effect besides the unchangedid
, so it's legal to do this (no one with an existing reference to astr
ever sees it change unless thestr
was logically being replaced).You're not actually supposed to rely on it (non-reference counted interpreters can't use this trick, since they can't know if the
str
has other references), per PEP8's very first programming recommendation:If you want to break the optimization, there are all sorts of ways to do so, e.g. changing your code to:
breaks it by creating an alias, increasing the reference count and telling Python that the change would be visible somewhere other than
s
, so it can't apply it. Similarly, code like:can't use it, because
s + a
occurs first, and produces a temporary thatb
must then be added to, rather than immediately replacings
, and the optimization is too brittle to try to handle that. Almost identical code like:or:
restores the optimization by ensuring the final concatenation is always one where
s
is the left operand and the result is used to immediately replaces
.无论实施细节如何, docs 说::
s
引用的上一个对象不再存在+=
,因此新对象通过拥有相同的id
来违反规则。Regardless of implementation details, the docs say:
The previous object referenced by
s
no longer exists after the+=
so the new object breaks no rules by having the sameid
.如果对象具有不重叠的寿命,则其ID值可能相同,但是如果变量重叠的寿命,因此它们必须具有不同的ID值。
If objects have non-overlapping lifetimes, their id values may be the same, but if variables have overlapping lifetimes so they must have different id values.
在C,Java或其他一些编程语言中,变量是连接到内存位置的标识符或名称。
例如
但是在Python中,变量被认为是与某个值相关的标签。 Python将价值视为对象。它可以保存内存并分配内存位置相对于值而不是变量。
变量相同,但是如果值不同,则可以分配新的内存,在更近的外观中,可以引用变量a = 10,然后由垃圾收集器删除,而新值则保持在新的内存位置中的变量。
在C中,Java内存位置是可变的,但在Python中,内存位置是用于值的值,可以将其视为对象。
In C, Java, or some other programming languages, a variable is an identifier or a name, connected to a memory location.
e.g.
but in Python, a variable is considered a tag that is tied to some value. Python considers value as an object. and it can save memory and assign memory location with respect to value instead of variable.
Variables are the same but if values are different then it can assign new memory, in a closer look no variable can be referenced a=10 then it is removed by the garbage collector and a new value hold the variable in a new memory location.
In C, Java memory location is for variable but in Python, the memory location is for value which can be treated as an object.