Python 奇怪的行为与明显的“缓存”有关;{};
今天我了解到Python缓存表达式Python 奇怪的行为与明显的“缓存”有关;{};,python,Python,今天我了解到Python缓存表达式{},并在将其分配给变量时用新的空dict替换它: print id({}) # 40357936 print id({}) # 40357936 x = {} print id(x) # 40357936 print id({}) # 40356432 我没有看过源代码,但我有一个想法,这可能是如何实现的。(可能当全局{}的引用计数增加时,全局{}被替换。) 但请考虑一下: def f(x): x['a'] = 1 print(id(x
{}
,并在将其分配给变量时用新的空dict替换它:
print id({})
# 40357936
print id({})
# 40357936
x = {}
print id(x)
# 40357936
print id({})
# 40356432
我没有看过源代码,但我有一个想法,这可能是如何实现的。(可能当全局{}
的引用计数增加时,全局{}
被替换。)
但请考虑一下:
def f(x):
x['a'] = 1
print(id(x), x)
print(id(x))
# 34076544
f({})
# (34076544, {'a': 1})
print(id({}), {})
# (34076544, {})
print(id({}))
# 34076544
f
修改全局dict而不导致其被替换,并打印出修改后的dict。但是在f
之外,尽管id相同,全局dict现在为空
发生了什么事???它没有被缓存——如果你没有将{}
的结果分配到任何地方,它的引用计数是0,它会被立即清除。碰巧您分配的下一个内存重用了旧内存。当您将其分配给x
时,您将使其保持活动状态,然后下一个将具有不同的地址
在函数示例中,一旦
f
返回,就没有对dict的剩余引用,因此它也会被清除,同样的事情也会发生。Python在这里不做任何缓存。当id()
在程序中的不同点给出相同的返回值时,有两种可能性:
id()
id()
的第一个对象进行了垃圾收集,并在与原始对象相同的内存位置创建了第二个对象在这种情况下,它是第二个。这意味着即使
打印id({});打印id({})
可以打印相同的值两次,每次调用都针对一个不同的对象。您可能还对这个问题感兴趣:非常酷的edge case,感谢您的分享。Python的id()
使用内存地址(至少在CPython实现中)作为对象的id。它只是在单个时间点上的唯一标识符,而不是在程序的整个生命周期中的唯一标识符。这在文档中是明确的:注意这是非常依赖于实现的:在第一个示例中调用四次id()
,在PyPy中会得到不同的值(在第一次调用之后,它们会下降16),在Jython和IronPython中(它们每次增加一个)。@DSM你说得对,它完全依赖于实现。确切的值甚至比这个还要糟糕:在CPython上,使用默认的PyPy配置,这些值是内存地址,在相同程序的相同运行之间可能会有所不同。回答得很好,感谢您解释了“缓存”(我认为这是一种相当可疑的优化)