Python是如何处理字符串的魔法的?

6 投票
1 回答
2690 浏览
提问于 2025-04-19 23:14

今天我对字符串比较感到困惑:似乎Python会重用字符串(这其实是个明智的做法,因为字符串是不可变的)。为了验证这一点,我做了以下测试:

>>> a = 'xxx'
>>> b = 'xxx'
>>> a == b
True
>>> a is b
True
>>> id(a)
140141339783816
>>> id(b)
140141339783816
>>> c = 'x' * 3
>>> id(c)
140141339783816
>>> d = ''.join(['x', 'x', 'x'])
>>> id(d)
140141339704576

这有点让人惊讶。于是我有几个问题:

  • Python在定义新字符串时,会检查它的字符串表中的所有内容吗?
  • 字符串的大小有没有限制?
  • 这个机制是怎么运作的(是通过比较字符串的哈希值吗?)
  • 不过,这似乎并不是对所有生成的字符串都适用。那么这里有什么规则呢?

1 个回答

0

因为这个问题有一些赞同票(虽然它有点重复),我在这里回答我最初的问题(感谢上面的评论):

  1. 是的,Python会检查内部表的所有内容:但只针对某些字符串,主要是那些也可以用作标识符的字符串。这个做法的想法是,Python解释器(编译器?)用来处理标识符的加速技巧,对于一般的字符串处理也是有用的。这个过程叫做 interning
  2. 据我所知,字符串的大小没有限制,但有其他规则来决定字符串是否可以被重用(主要是:它们必须看起来像Python的标识符)。
  3. 是的,这个表是一个普通的Python字典,字符串有一个哈希值用于查找。
  4. 它只用于字符串字面量和常量表达式。基本上是所有Python解释器在编译阶段可以推断出来的东西。

为了澄清最后一点,以下代码片段在所有情况下都评估为字符串 'xxx',但在处理interning时却是不同的。

这是一个常量表达式:

'x' * 3

但这不是:

a = 'x'
a * 3   # this is no constant expression, so no interning can be applied.

而这不是表达式:

''.join(['x', 'x', 'x']) # this is no expression (a function is called)

撰写回答