Python:解释器中的id()行为[重复]

发布于 2021-01-29 14:58:25

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

Python何时为相同的字符串分配新的内存? (5个答案)

7年前关闭。

我遇到了这种奇怪的行为,这种行为仅在交互式Python会话中发生,而在编写脚本并执行时却没有。

在Python中,字符串是不可变的数据类型,因此:

>>> s2='string'
>>> s1='string'
>>> s1 is s2
True

现在,奇怪的部分:

>>> s1='a string'
>>> s2='a string'
>>> s1 is s2
False

我已经看到,字符串中包含空格会导致此行为。如果将其放在脚本中并运行,则在两种情况下结果均为True。

有人对此有任何线索吗?谢谢。

编辑:

好的,上面的问题和答案给出了一些想法。现在这是另一个实验:

>>> s2='astringbstring'
>>> s1='astringbstring'
>>> s1 is s2
True

在这种情况下,字符串肯定比更长'a string',但仍具有相同的标识符。

关注者
0
被浏览
82
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    非常感谢@eryksun的更正!

    这是由于interningPython中的机制调用:

    在“
    interned”字符串表中输入string并返回被中断的字符串–它是字符串本身或副本。插入字符串对于提高字典查找的性能很有用–如果字典中的键被插入,并且查找键被插入,则键比较(散列后)可以通过指针比较而不是字符串比较来完成。通常,Python程序中使用的名称会被自动插入,并且用于保存模块,类或实例属性的字典具有插入键。

    在版本2.3中进行了更改:内联字符串不是不朽的(就像它们曾经在Python
    2.2及之前的版本中一样);您必须保留对intern()返回值的引用,以从中受益。

    CPython 会自动实习 某些字符串(1个字母字符串,关键字,没有分配空格的字符串)以提高查找速度和比较速度:例如,'dog' is 'dog'将是指针比较而不是完整的字符串比较。但是,对所有(较长)字符串的自动实习需要更多的内存,这并不总是可行的,因此它们可能不会共享相同的标识,从而导致结果id()不同,例如:

    # different id when not assigned
    In [146]: id('dog')
    Out[146]: 4380547672
    
    In [147]: id('dog')
    Out[147]: 4380547552
    
    # if assigned, the strings will be interned (though depends on implementation)
    In [148]: a = 'dog'
    
    In [149]: b = 'dog'
    
    In [150]: id(a)
    Out[150]: 4380547352
    
    In [151]: id(b)
    Out[151]: 4380547352
    
    In [152]: a is b
    Out[152]: True
    

    对于整数,至少在我的机器上,CPython会自动自动最多迭代256个:

    In [18]: id(256)
    Out[18]: 140511109257408
    
    In [19]: id(256)
    Out[19]: 140511109257408
    
    In [20]: id(257)
    Out[20]: 140511112156576
    
    In [21]: id(257)
    Out[21]: 140511110188504
    

    由于@eryksun而进行的更新 :在这种情况下,该字符串'a string'没有被插入,因为CPython仅插入没有空格的字符串,而不是因为我立即假定的长度:例如ASCII字母,数字和下划线。

    有关更多详细信息,您还可以在此处参考Alex
    Martelli的答案



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看