【问题标题】:How does python do string magic? [duplicate]python如何做字符串魔术? [复制]
【发布时间】:2014-10-29 23:35:22
【问题描述】:

我今天对字符串比较感到困惑:似乎 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 定义新字符串时是否检查其字符串表的全部内容?
  • 字符串大小有限制吗?
  • 这种机制是如何工作的(比较字符串的哈希值?)
  • 不过,它似乎并不适用于所有类型的生成字符串。这里的规则是什么?

【问题讨论】:

  • is 测试身份,即内存位置。 == 测试相等性。互换使用它们是不明智的,因为一些字符串、整数等以优化的名义被实习
  • 谢谢,但我已经知道了(我没有问过任何事情)。我的问题不是关于is==:而是关于python 如何在内部重用字符串。即关于python使用的内部实现来决定一个字符串不需要添加到它的字符串表中,但它可以被重用。正如您在我的示例中看到的那样,该机制不适用于所有相等的字符串,因此我想了解何时以及如何使用它。
  • 您可能对what Martijn Pieters has to say感兴趣
  • @inspectorG4dget:这正是我想要的,谢谢!请添加该答案,我接受。
  • @jeckyll2hide 我认为您想要的答案实际上是在linked dupe... Python 会将符合有效语法的字符串文字作为标识符或单个字符作为优化的一部分。 a = '$a'; b = '$b'; a is b 将是 False 例如

标签: python string python-internals


【解决方案1】:

由于这个问题有一些赞成票(虽然它有些重复),我将在这里回答我最初的问题(感谢上面的 cmets):

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

为了澄清最后一点,以下 sn-ps 在所有情况下都将评估为字符串 'xxx',但在实习方面它们的处理方式不同。

这是一个常量表达式:

'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)

【讨论】:

  • 这个答案只会增加混乱。 'x' * 3not 字符串文字,它是一个表达式。无论如何,结果是一个实现细节,由编译器完成的优化,它在编译时预先计算简单的表达式,例如1 + 1'x' * 3。在字符串的情况下,通常会应用看起来像标识符的字符串。在交互式提示中输入的表达式与 .py 文件经过完全相同的编译运行路径。
  • @user4815162342:那你怎么解释a = 'x' ; a * 3没有被实习?那也是一个表达式,生成的字符串满足interning的所有要求...
  • 也是一个表达式,但不是只涉及常量的表达式。当前的 CPython 编译器不够聪明,无法证明 a * 3 在这种情况下与 'x' * 3 相同。 (事实上​​,常量的编译时折叠是编译器中一个相对较新的功能,在 2.3-2.5 时间范围内的某个地方实现,如果我没记错的话。)
猜你喜欢
  • 2014-11-29
  • 2013-02-08
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-30
  • 1970-01-01
相关资源
最近更新 更多