Python - 打印出所有不可变对象

时间:2013-09-04 19:29:34

标签: python cpython

正如您之前可能已经注意到的,CPython有时会存储相同的不可变对象的单个副本。

e.g。

>>> a = "hello"
>>> b = "hello"
>>> a is b
True

>>> a, b = 7734, 7734
>>> a is b
True

我认为堆的散列似乎是在类型推理

之后执行的
>>> a, b = 7734, 07734
>>> a is b
False

>>> a, b = 7734, 017066
>>> a is b
True

有没有办法反省解释器并打印出这个假定的不可变对象堆?

2 个答案:

答案 0 :(得分:8)

不,实习对象在一系列位置维护,没有一种方法可以列出所有这些对象。

  • 正如您所发现的那样,字符串可以被实习,您可以使用intern() function自行实习。
  • 介于-5到256之间的小整数。
  • 重复使用元组;空元组(())是一个单例,并且每个元组大小1到20都保持缓存以便循环使用。 (只是元组对象,而不是内容)。
  • None是单身,EllipsisNotImplementedTrueFalse也是。
  • 从Python 3.3开始,实例__dict__字典可以share keys保存在内存中。
  • 编译器可以将不可变(在某些情况下,可变)源代码文字标记为常量,将它们与字节码一起存储,并在每次运行字节码时重复使用它们。这适用于字符串,数字,元组,列表(如果与in语句一起使用)和as of Python 3.2集(再次与in一起使用时)。

可能还有更多我尚未发现。

这些优化都有助于避免过多的堆流失。除了NoneEllipsisNotImplementedTrueFalse是单例之外,它们都是特定于CPython的优化,它们不是Python的一部分语言定义本身。

答案 1 :(得分:3)

这比你做到的要复杂一点。例如,在具有大整数的示例中,当使用不属于同一表达式时,同一对象重用。

>>> a = 7734
>>> b = 7734
>>> a is b
False

另一方面,正如您的第一个示例所示,这适用于字符串...但不是所有字符串。

>>> a = "this string includes spaces"
>>> b = "this string includes spaces"
>>> a is b
False

以下对象实际上是默认实现的:小整数,空元组和看起来像Python标识符的字符串。您在大整数和其他不可变对象中看到的是一种优化,因为它们被用在同一个表达式中。