【问题标题】:How is python storing strings so that the 'is' operator works on literals?python如何存储字符串以便'is'运算符适用于文字?
【发布时间】:2016-10-12 21:54:26
【问题描述】:

在python中

>>> a = 5
>>> a is 5
True

但是

>>> a = 500
>>> a is 500
False

这是因为它将低整数存储为单个地址。但是一旦数字开始变得复杂,每个 int 都有自己唯一的地址空间。这对我来说很有意义。

当前的实现为 -5 到 256 之间的所有整数保留一个整数对象数组,当您在该范围内创建一个 int 时,实际上您只是获取对现有对象的引用。

那么现在,为什么这不适用于字符串?字符串不是和大整数一样复杂吗(如果不是更复杂的话)?

>>> a = '1234567'
>>> a is '1234567'
True

python 如何有效地为所有字符串文字使用相同的地址?它不能像对数字那样保留所有可能的字符串的数组。

【问题讨论】:

    标签: python string


    【解决方案1】:

    这是一种称为实习的优化技术。 CPython 识别equal values of string constants 并且不会为新实例分配额外的内存,而是简单地指向同一个(实习生),给两个相同的id()

    可以确认只有常量会以这种方式处理(可以识别b 等简单操作):

    # Two string constants
    a = "aaaa"
    b = "aa" + "aa"
    
    # Prevent interpreter from figuring out string constant
    c = "aaa"
    c += "a"
    
    print id(a)         # 4509752320
    print id(b)         # 4509752320
    print id(c)         # 4509752176 !!
    

    但是,您可以使用intern() 手动强制将字符串映射到现有的字符串:

    c = intern(c)
    
    print id(a)         # 4509752320
    print id(b)         # 4509752320
    print id(c)         # 4509752320 !!
    

    其他口译员的做法可能有所不同。由于字符串是不可变的,因此更改两者之一不会更改另一个。

    【讨论】:

    • 看起来预定义整数的范围是 -5 到 +256。所有其他人似乎都是从文字中动态创建的,因此“is”返回 False。
    • 没有标记为答案,因为您说“它的优化”但没有解释它是如何存储的,这是问题所在。或者换句话说,他们是如何进行优化的。
    【解决方案2】:

    它不存储所有可能字符串的数组,而是有一个哈希表,指向所有当前声明的字符串的内存地址,由字符串的哈希索引。

    例如

    当您说a = 'foo' 时,它首先对字符串foo 进行哈希处理并检查哈希表中是否已存在条目。如果是,那么变量a 现在引用该地址。

    如果在表中没有找到条目,python分配内存来存储字符串,散列foo并在表中添加一个带有分配内存地址的条目。

    见:

    1. How is the 'is' keyword implemented in Python?
    2. https://en.wikipedia.org/wiki/String_interning

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2012-03-31
    • 2017-10-18
    • 1970-01-01
    • 2014-07-13
    • 2016-07-19
    • 2018-12-21
    相关资源
    最近更新 更多