简体   繁体   English

可变和不可变的对象

[英]Mutable and Immutable Objects

I am trying to get my head around on mutable and immutable objects. 我试图了解可变和不可变的对象。 I have read that string is immutable and that for each string, a separate object is created with a different object ID. 我已经读过字符串是不可变的,并且对于每个字符串,使用不同的对象ID创建单独的对象。 I am trying to verify this using below simple code, however, I see same object ID for multiple strings which are not same. 我试图使用下面的简单代码验证这一点,但是,我看到多个不相同的字符串的相同对象ID。 Can someone please clarify this. 有人可以澄清一下。 Thanks in advance. 提前致谢。

mystring = ""
mylist = ["This ", "That ", "This ", "That ", "This ", "That ", "This ", "That "]

for item in mylist:
    mystring = mystring + item
    print("mystring: ", mystring, "ID of mystring: ", id(mystring))

which results in below output: 这导致以下输出:

mystring:  This  ID of mystring:  6407264
mystring:  This That  ID of mystring:  42523448
mystring:  This That This  ID of mystring:  42523448
mystring:  This That This That  ID of mystring:  6417200
mystring:  This That This That This  ID of mystring:  42785608
mystring:  This That This That This That  ID of mystring:  42785608
mystring:  This That This That This That This  ID of mystring:  42837536
mystring:  This That This That This That This That  ID of mystring:  42775856

Python is allowed to reuse object IDs for objects with non-overlapping lifetimes, but you're seeing ID reuse in cases where there should be a lifetime overlap. 允许Python为具有非重叠生命周期的对象重用对象ID,但是在应该存在生命周期重叠的情况下,您会看到ID重用。 Specifically, during execution of this statement: 具体而言,在执行此声明期间:

mystring = mystring + item

between the evaluation of mystring + item and the assignment to mystring , there should be a lifetime overlap between any two successive values of mystring . 的评价之间mystring + item和分配到mystring ,应该有任何两个连续值之间的寿命重叠mystring You're seeing ID reuse for successive values of mystring , which shouldn't happen. 你看到ID重复使用的连续值mystring ,这是不应该的。

The effect you're seeing happens because of an optimization in the CPython bytecode evaluation loop, where statements of the form 您看到的效果是因为CPython字节码评估循环中的优化,其中表单的语句

string1 = string1 + string2

or 要么

string1 += string2

are detected, and if the interpreter can confirm that string1 has no other references, it attempts to perform the concatenation by mutating string1 in-place. 检测到,如果解释器可以确认string1没有其他引用,它会尝试通过原位改变string1来执行连接。 You can see the code in Python/ceval.c under unicode_concatenate . 你可以看到在代码Python/ceval.cunicode_concatenate This optimization is mostly invisible, due to the refcount check, but the effect on id values is one way it's visible. 由于引用计数检查,此优化通常是不可见的,但对id值的影响是其可见的一种方式。

String are immutable. 字符串不可变的。 There exist no str method that allows to mutate them. 不存在允许改变它们的str方法。

That being said, the reason you see the same id multiple times is because when an object is no longer in use, Python will reuse its position in memory. 话虽这么说,你多次看到相同id的原因是因为当一个对象不再使用时,Python将重用它在内存中的位置。 And what id does is precisely to provide a unique identifier by returning the position of the object in memory. id作用恰恰是通过返回对象在内存中的位置来提供唯一标识符。

One way to convince yourself that this is indeed the reason for your observation would be to make sure to always have a reference to each of the string you create by adding them to a list . 一种说服自己确实是你观察的原因的方法是确保始终通过将每个字符串添加到list来引用它们。

Code

mystring = ""
mylist = ["This ", "That ", "This ", "That ", "This ", "That ", "This ", "That "]

# A list to keep a reference to each string
created_strings = []

for item in mylist:
    mystring = mystring + item

    # Prevent mystring from being garbage collected by adding it to the list
    created_strings.append(mystring)

    print("mystring: ", mystring, "ID of mystring: ", id(mystring))

Output 产量

mystring:  This  ID of mystring:  2522900655888
mystring:  This That  ID of mystring:  2522903930416
mystring:  This That This  ID of mystring:  2522903930544
mystring:  This That This That  ID of mystring:  2522902118880
mystring:  This That This That This  ID of mystring:  2522900546624
mystring:  This That This That This That  ID of mystring:  2522900546864
mystring:  This That This That This That This  ID of mystring:  2522902428376
mystring:  This That This That This That This That  ID of mystring:  2522900907952

Notice that now that memory is not reclaimed, each object has a different id . 请注意,现在内存未被回收,每个对象都有不同的id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM