与“{}”的明显缓存相关的奇怪行为

时间:2013-03-27 19:23:54

标签: python

今天我了解到Python缓存了表达式{},并在分配给变量时将其替换为新的空字典:

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修改全局字典而不会导致它被替换,并打印出修改后的字典。但是在f之外,尽管id是相同的,全局字典现在是空的!

发生了什么事?

2 个答案:

答案 0 :(得分:6)

它没有被缓存 - 如果你没有在任何地方分配{}的结果,它的引用计数为0并且它立即被清除。碰巧你分配的下一个重用了旧的内存。当您将其分配给x时,您将其保持活动状态,然后下一个具有不同的地址。

在你的函数示例中,一旦f返回,就没有对你的dict的剩余引用,所以它也会被清除,同样适用。

答案 1 :(得分:4)

Python没有在这里进行任何缓存。当id()在程序中的不同点给出相同的返回值时,有两种可能性:

  1. id()在同一个对象上被调用两次
  2. 调用id()的第一个对象是在创建第二个对象之前进行了垃圾收集,第二个对象是在与原始对象相同的内存位置创建的
  3. 在这种情况下,它是第二个。这意味着即使print id({}); print id({})可以打印两次相同的值,每次调用都在一个不同的对象上。