python如何做魔术?

dan*_*ast 6 python string python-internals

今天我被一个字符串比较困惑:似乎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
Run Code Online (Sandbox Code Playgroud)

这有点令人惊讶.一些问题:

  • python在定义新字符串时是否检查其字符串表的全部内容?
  • 字符串大小有限制吗?
  • 这个机制是如何工作的(比较字符串的哈希值?)
  • 它似乎并不用于所有类型的生成字符串.这里的规则是什么?

dan*_*ast 0

由于这个问题有一些赞成票(尽管有点重复),我将在这里回答我原来的问题(感谢上面的评论):

  1. 是的,python 检查内表的全部内容:但只检查某些字符串,大多数是那些也可以用作标识符的字符串。这个想法是,Python 解释器(编译器?)用于标识符处理的加速技巧对于通用字符串处理也很有用。这个过程称为实习
  2. 据我所知,字符串大小没有限制,但是重用字符串还有其他规则(主要是:它们必须看起来像Python标识符)
  3. 是的,该表是一个普通的 python 字典,并且字符串具有用于查找的哈希值。
  4. 它仅用于字符串文字和常量表达式。基本上对于 python 解释器在编译阶段可以推断的所有事情。

为了澄清最后一点,以下代码片段在所有情况下都会评估 string 'xxx',但在实习方面它们的处理方式有所不同。

这是一个常量表达式:

'x' * 3
Run Code Online (Sandbox Code Playgroud)

但这不是:

a = 'x'
a * 3   # this is no constant expression, so no interning can be applied.
Run Code Online (Sandbox Code Playgroud)

这不是表达:

''.join(['x', 'x', 'x']) # this is no expression (a function is called)
Run Code Online (Sandbox Code Playgroud)