python内存如何管理字符串对象?

python内存如何管理字符串对象?,python,python-3.x,cpython,Python,Python 3.x,Cpython,为什么我们会变得虚假,因为 任何人都可以解释python的内存行为 让我们首先研究一下id()的作用: 返回对象的“标识”。这是一个整数,保证该对象在其生存期内唯一且恒定。两个生命周期不重叠的对象可能具有相同的id()值 CPython实现细节:这是内存中对象的地址 好的,一般来说,当两个名称指向完全相同的对象时,它们将具有相同的id() 那么我们为什么要这样做呢 str1 = 'aaa' str2 = 'aaa' print(id(str1) == id(str2)) # True 这是因

为什么我们会变得虚假,因为

任何人都可以解释python的内存行为


让我们首先研究一下
id()
的作用:

返回对象的“标识”。这是一个整数,保证该对象在其生存期内唯一且恒定。两个生命周期不重叠的对象可能具有相同的id()值

CPython实现细节:这是内存中对象的地址

好的,一般来说,当两个名称指向完全相同的对象时,它们将具有相同的
id()

那么我们为什么要这样做呢

str1 = 'aaa'
str2 = 'aaa'
print(id(str1) == id(str2)) # True 
这是因为,在(Python的C参考实现)中,字符串被缓存在哈希表中(出于性能原因),让
str1
str2
指向同一内存更便宜。 请注意,这可以在没有太多意外行为的情况下完成,因为字符串在Python中是不可变的。 但是,此机制仅对以下字符串触发,例如:

任何在解释器内动态创建
str
的机制(即除了
eval()
)都不在缓存范围内,如您的示例所示,或者:

True  
True a a
True aa aa
True aaa aaa
True aaaa aaaa

为了进一步参考,Python中字符串的内部表示在中有更详细的描述。

为什么它很重要?如果要测试字符串是否相等,请使用
=
运算符。这里发生的是某种可能特定于cpythontanks的内存使用优化,但是CPython在做哪种类型的内存优化,你知道吗?我对这个问题也很好奇。既然str1和str2是不同的字符串,它们不应该有不同的ID吗?或者因为它们指向同一个对象,所以它们具有相同的内存地址?这也发生在小于等于256的整数中。可能是某种优化,没什么大不了的。这确实是一个非常好的答案!也许值得注意一点Python中的一般引用(例如
a='456'
b='456'
将指向同一个指针,而
a=456
b=456
将不指向),这会一直触发,直到
256
@norok2我理解字符串intern和caching,但我仍然不完全理解原始循环。为什么从迭代3开始,它们的计算结果为false?@CathalCronin否,短路发生在
s*0
s*1
上,对于任何字符串,在代码中的任何点。这两个操作不生成动态字符串,而是分别获取指向空字符串和
s
本身的指针@简而言之,CathalCronin:如果发生常量折叠(长度为1的字符串),则字符串在编译时被插入,但对于在运行时创建的字符串(其他字符串)则不被插入
str1 = 'aaa'
str2 = 'aaa'
print(id(str1) == id(str2)) # True
for i in range(5):
    a = eval('"' + 'a' * i + '"')
    b = eval('"' + 'a' * i + '"')
    print(id(a) == id(b), a, b)
True  
True a a
True aa aa
True aaa aaa
True aaaa aaaa
a = 'aaa'
b = a[1:]
c = 'aa'
print(id(b) == id(c))
# False
print(id(b) == id(a[1:]))
# False