首页 > 解决方案 > python是字符串的运算符行为

问题描述

我无法理解以下行为。我正在创建 2 个字符串,并使用 is 运算符进行比较。在第一种情况下,它的工作方式不同。在第二种情况下,它按预期工作。当我使用逗号或空格时是什么原因,它False在比较时显示is,当没有使用逗号或空格或其他字符时,它给出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 以不同方式解释字符串的可靠信息?我最初理解这一点,a并且b指的是同一个对象。然后b得到一个新对象,仍然b is aTrue。理解这种行为有点令人困惑。

当我使用“字符串”执行此操作时 - 它会产生相同的结果。当我使用 '1,2,3,4' 时出了什么问题 - 它们都是字符串。案例 1 和案例 2 有什么不同?即is运算符为字符串的不同内容产生不同的结果。

标签: pythonpython-3.xidentitypython-internals

解决方案


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

现在,出现这种奇怪行为的原因是 Python(CPython 实现)在实习方面对字符串的处理方式不同。在 Python 的源代码中,有一个intern_string_constants函数,它为字符串提供了要被实习的验证,您可以检查以获取更多详细信息。或者查看这篇综合文章http://guilload.com/python-string-interning/

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

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

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

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

当您想加快字典查找或应该在代码中频繁使用特定字符串对象时,您可以使用此功能。

您不应该与字符串实习混淆的另一点是,当您这样做时a == b,您正在创建对同一对象的两个引用,这对于那些关键字具有相同的id.

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

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

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


推荐阅读