Python是如何处理字符串的魔法的?
今天我对字符串比较感到困惑:似乎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
因为这个问题有一些赞同票(虽然它有点重复),我在这里回答我最初的问题(感谢上面的评论):
- 是的,Python会检查内部表的所有内容:但只针对某些字符串,主要是那些也可以用作标识符的字符串。这个做法的想法是,Python解释器(编译器?)用来处理标识符的加速技巧,对于一般的字符串处理也是有用的。这个过程叫做 interning。
- 据我所知,字符串的大小没有限制,但有其他规则来决定字符串是否可以被重用(主要是:它们必须看起来像Python的标识符)。
- 是的,这个表是一个普通的Python字典,字符串有一个哈希值用于查找。
- 它只用于字符串字面量和常量表达式。基本上是所有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)