【问题标题】:python is operator behaviour with string [duplicate]python是字符串的运算符行为[重复]
【发布时间】:2018-10-06 19:58:23
【问题描述】:

我无法理解以下行为。我正在创建 2 个字符串,并使用 is 运算符进行比较。在第一种情况下,它的工作方式不同。在第二种情况下,它按预期工作。什么原因当我使用逗号或空格时,它显示Falseis 比较,当没有使用逗号或空格或其他字符时,它给出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。理解这种行为有点令人困惑。

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

【问题讨论】:

  • 我了解 == 的工作原理。我不是在这里指==。它完全是。检查我的代码并查看帖子参考更改,它仍然产生相同的结果。
  • @deceze 这个问题不是关于身份和值检查,而是关于 Python 缓存字符串的不同方式(字符串实习)。
  • @khelwood 这看起来像是一个微妙不同的问题。为什么is操作符在执行相同操作但字符串内容不同时会改变结果。
  • 是的,这个问题有些问题。如果你只有a = '1,',然后b = '1,',那么它们显然是不同的对象。与哪些字符串被实习有关的事情有些神秘。

标签: python python-3.x identity python-internals


【解决方案1】:

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

现在,您出现这种奇怪行为的原因是 Python(CPython 实现)在实习方面对字符串的处理方式不同。在 Python 的源代码中,有一个 intern_string_constants 函数,它为字符串提供了要实习的验证,您可以查看更多详细信息。或者查看这篇综合文章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

当你想fasten the dictionary lookups 或者你应该在你的代码中频繁使用一个特定的字符串对象时,你可以使用这个函数。

您不应该与 字符串实习 混淆的另一点是,当您执行 a == b 时,您正在创建对同一个对象的两个引用,这对于这些关键字具有相同的 @ 是显而易见的987654329@.

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

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

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

【讨论】:

  • 我知道python会创建一个字符串池以使它们更易于访问,但是11,之间有什么区别导致它们具有不同的ID?
  • 此外,我意识到如果我使用像a = b = c = '1,' 这样的多个赋值,它们都有相同的id。此声明的链接:stackoverflow.com/questions/35275026/…
  • 看源码。关键点:我们在这里不是在谈论 Python,而是在谈论 Python (CPython) 的一种实现。 PyPy 的行为可能会有所不同。
  • @BcK 正如我提到的,这是一个 Cpython 实现细节,您可以查看源代码。关于该分配,请检查更新。
  • @BcK 查看更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多