2014-09-05 72 views
6

我今天被一个字符串比较弄糊涂了:看起来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是否检查其字符串表的全部内容?
  • 字符串大小是否有限制?
  • 这种机制是如何工作的(比较字符串的散列?)
  • 虽然它似乎并不适用于所有类型的生成字符串。这里的规则是什么?
+0

'is'测试的身份,即存储位置。 '=='测试相等性。这是不明智的交替使用它们,因为一些字符串,整数等被优化的名称 – inspectorG4dget 2014-09-05 04:43:31

+0

谢谢,但我已经知道(我没有询问任何有关它)。我的问题不是关于'is'还是'==':它关于内部python如何重用字符串。也就是说,关于python用来决定一个字符串不需要添加到其字符串表的内部实现,但它可以被重用。正如你在我的例子中看到的那样,这个机制并不适用于所有相同的字符串,所以我想了解它何时以及如何使用它。 – dangonfast 2014-09-05 04:51:36

+4

您可能感兴趣的内容[Martijn Pieters说的](https://www.codementor.io/python-tutorial/stack-overflow-martijn-pieters-python-optimization?utf-xml:utm_source = reddit-content&utm_medium = blog&utm_term = python-tutorial-python-internals&utm_content = blog&utm_campaign = reddit-content) – inspectorG4dget 2014-09-05 04:55:49

回答

0

由于这个问题有一些upvotes(虽然它是一个重复的有点),我会在这里回答我原来的问题(感谢上述评论):

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

为了澄清最后一点,以下片段在所有情况下都会对字符串'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) 
+0

这个答案只会增加混乱。 ''x'* 3'是**不是**字符串,它是一个表达式。结果无论如何都是一个实现细节,一个由编译器完成的优化,在编译时预先计算诸如“1 + 1”或“x'* 3”的简单表达式。在字符串的情况下,通常会使用看起来像标识符的字符串。在交互式提示符下输入的表达式与'.py'文件完全相同的编译运行路径。 – user4815162342 2014-09-05 09:00:05

+0

@ user4815162342:那么你如何解释'a ='x'; a * 3'没有被拦截?这也是一个表达式,并且由此产生的字符串满足实习内容的所有要求... – dangonfast 2014-09-05 09:19:56

+0

它也是一个表达式,但不是只涉及常量的表达式。目前的CPython编译器不够巧妙,无法证明'a * 3'在这种情况下与''x'* 3'相同。 (实际上,常量的编译时折叠是编译器的一个相对较新的特性,如果内存为我服务,那么在2.3-2.5的时间范围内实现。) – user4815162342 2014-09-05 09:28:59