为什么我的变量有那么多引用计数?

问题描述

尝试理解Python GIL(在Python 3.7.6中。 ),我玩过sys.getrefcount(),结果有些奇怪。

documentationsys.getrefcount(object)

返回对象的引用计数。返回的计数通常比您预期的高一,因为它包含(临时)引用作为getrefcount()的参数。

为了尝试自己动手做,这是进度/困惑:

首先,sys.getrefcount(object)是否应该处理值/文字? (如果我输入错了,请更正我的用语), 为什么引用计数如此随机

>>> import sys
>>> [sys.getrefcount(i) for i in range (10)]
[320,195,128,43,69,24,32,18,44,17]
>>> [sys.getrefcount(str(i)) for i in range (10)] #refcount of every value is same Now (?)
[1,1,1]

然后,我尝试进一步探索

>>> # Let's probe further
>>> import random
>>> [sys.getrefcount(str(random.randint(1,20))) for i in range (10)]
[1,1]
>>> [sys.getrefcount(str(random.randint(1,20)*'a')) for i in range (10)]
[1,14,1] # not every item is same
>>> [sys.getrefcount(random.choice('abcde')) for i in range (10)]
[20,20,12,9,13,12]
>>> [sys.getrefcount(str(random.choice('abcde'))) for i in range (10)]
[9,12]

上面发生了什么事?我不确定是否可以仅凭我可能会有的一种误解来解释所有行为,或者在这里有多种作用。请放心,假设上述行在Python Interpreter中按顺序运行,并且这里没有其他内容

为了使问题更有意义,一切都从这里开始:

>>> sys.getrefcount(1)
187
>>> a = 1
>>> sys.getrefcount(a)
185

编辑:我明白了,但是sys.getrefcount(1)为什么应该这么高?

解决方法

首先,sys.getrefcount(object)是否可以处理值/文字? (如果我输入错误,请更正我的用语)

是的。文字是返回对象的表达式。该对象可能被缓存(例如,较小的数字),也可能未被缓存(任意字符串)。

,为什么引用计数如此随机?

口译员的巧合/特质

>>> [sys.getrefcount(i) for i in range (10)]
[320,195,128,43,69,24,32,18,44,17]

小数文字在CPython中缓存;它们都引用内存中的同一对象,而内存中的任何对象都引用它们。在这种情况下,CPython可能会为循环保留对小数缓存的引用。

>>> [sys.getrefcount(str(i)) for i in range (10)] #refcount of every value is same now (?)
[1,1,1]

这些是新对象,不在缓存中搜索。

对于其他情况,通常会缓存字符串,并且某些引用当时在内存中。

>>> sys.getrefcount(1)
187
>>> a = 1
>>> sys.getrefcount(a)
185

a仅仅是对(通常已缓存的)“ 1”的引用,引用计数之间的任何差异都可能指的是REPL为了引用文字并进行打印而进行的任何处理。