问题描述
尝试理解Python GIL(在Python 3.7.6中。
),我玩过sys.getrefcount()
,结果有些奇怪。
从documentation到sys.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为了引用文字并进行打印而进行的任何处理。