python 是字符串的运算符行为

python is operator behaviour with string

我无法理解以下行为。我正在创建 2 个字符串,并使用 is 运算符对其进行比较。在第一种情况下,它的工作方式不同。在第二种情况下,它按预期工作。当我使用逗号或 space 时,它显示 Falseis 比较时的原因是什么,当没有使用逗号或 space 或其他字符时,它给出 True

Python 3.6.5 (default, Mar 30 2018, 06:41:53) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 'string'
>>> b = a
>>> b is a
True
>>> b = 'string'
>>> b is a
True
>>> a = '1,2,3,4'
>>> b = a
>>> b is a
True
>>> b = '1,2,3,4'
>>> b is a
False

是否有关于 python 为什么以不同方式解释字符串的可靠信息?我知道最初 ab 指的是同一个对象。然后b得到一个新对象,还是b is aTrue。理解这种行为并不容易混淆。

当我使用 'string' 时 - 它会产生相同的结果。当我使用 '1,2,3,4' 时出了什么问题 - 它们都是字符串。 case 1 和 case 2 有什么不同?即 is 运算符对字符串的不同内容产生不同的结果。

关于此行为的一件重要事情是 Python 缓存了一些,大部分是短字符串(通常少于 20 个字符,但不是针对它们的所有组合),以便可以快速访问它们。一个重要的原因是字符串在 Python 的源代码中被广泛使用,并且它是一种内部优化来缓存一些特殊类型的字符串。字典是 Python 源代码中常用的数据结构之一,通常用于保存变量、属性和名称空间,以及其他一些目的,它们都使用字符串作为对象名称。这就是说,每次您尝试访问对象属性或访问变量(本地或全局)时,都会在内部触发字典查找。

现在,您出现这种奇怪行为的原因是 Python(CPython 实现)在实习方面对字符串的处理方式不同。在Python的源代码中,有一个intern_string_constants function that gives strings the validation to be interned which you can check for more details. Or check this comprehensive article http://guilload.com/python-string-interning/.

还值得注意的是,Python 在 sys 模块中有一个 intern() 函数,您可以使用它来手动实习字符串。

In [52]: b = sys.intern('a,,')

In [53]: c = sys.intern('a,,')

In [54]: b is c
Out[54]: True

您可以在需要时使用此函数 或者当您应该在代码中经常使用特定字符串对象时。

另一点你不应该与 string interning 混淆的是,当你做 a == b 时,你创建了对同一个对象的两个引用,这对于这些关键字具有相同的 id.

关于标点符号,似乎如果它们是一个字符,如果它们的长度超过一个,它们就会被拘留。如果长度大于 1,它们将不会被缓存。正如评论中提到的,其中一个原因可能是关键字和字典键不太可能包含标点符号。

In [28]: a = ','

In [29]: ',' is a
Out[29]: True

In [30]: a = 'abc,'

In [31]: 'abc,' is a
Out[31]: False

In [34]: a = ',,'

In [35]: ',,' is a
Out[35]: False

# Or

In [36]: a = '^'

In [37]: '^' is a
Out[37]: True

In [38]: a = '^%'

In [39]: '^%' is a
Out[39]: False

但是,这些只是您不能在代码中依赖的一些推测。