【问题标题】:python id() different behaviour within and outside a functionpython id() 函数内外的不同行为
【发布时间】:2021-09-11 21:16:14
【问题描述】:

我正在尝试用 id 来理解 python 中的默认值

def f(x=5000):
    print(id(x))
    x=40000
    print(id(x))
    print()
    

f()

f()

这给出了输出

2187265500336
2187265501488

2187265500336
2187265501488

我明白为什么第一个打印语句是相同的。这是因为在定义函数时会计算默认值 x。

但是,在这两种情况下,第二个打印语句都给出了相同的 id,这让我感到困惑,我无法在其他地方在线找到答案。考虑

a=100000
print(id(a))

a=400000
print(id(a))

a=100000
print(id(a))

a=400000
print(id(a))

这给出了输出

2187265558768
2187265558608
2187265559440
2187265558032

是什么导致了这两种情况的不同?在函数内部,当我们在不同的函数调用中重新分配变量时,它会获得相同的 id,但是当我们将变量重新分配给与之前在函数外部相同的值时,这种情况不会发生

编辑以回应@Barmar 的评论和链接understanding python id() uniqueness 的问题。我有点理解,但不完全。我现在最好的猜测是 (1)如评论中所述,内存可供将来使用 (2) 在下面的示例中,即使分配了其他内存,每次都将相同的内存分配给 x 似乎有一些潜在的原因。这是因为缓存优化吗?

缓存优化意味着在人们可能天真地认为应该得到新对象的情况下,并不总能保证得到一个新对象,但这绝不会违反 ID 的唯一性保证。像 int 和 str 这样的内置类型可能有一些缓存优化,但它们遵循完全相同的规则:如果它们同时存在,并且它们的 ID 相同,那么它们就是同一个对象。

def f(x=5000):
    print(id(x))
    c=23000
    d=12444
    x=40000

    w=23444

    print(id(x))
    print()
    

f()

f()
2187265559440
2187265559376

2187265559440
2187265559376

这里我们分配了几个新变量,但每次重新分配时,相同的 id 都被分配给变量 x。

关于@dont just talk code's comment

如果你再试几次,它可能会。

然后我用以下方法进行了尝试,但重复一百万次后仍然得到相同的结果

def f(x=5000):
    id_1 = id(x)
    c=23000
    d=12444
    x=40000

    w=23444

    id_2 = id(x)
    return (id_1, id_2)

[f() for n in range(1000000)] == [f() for n in range(1000000)]
True

【问题讨论】:

  • 当您离开该功能时,x 的内存可供将来使用。下次调用该函数时,恰好得到相同的内存,所以ID是一样的。
  • @Barmar 为什么不给出更多解释并以此作为答案?
  • 我确定存在重复项,只是没有指向它们的链接。
  • 内存是否被重用只是分配模式的意外。
  • 内存被重用绝非偶然,@Barmar 错了。看看f.__code__.co_consts。第二个条目是整数40000。它在函数编译期间被存储为常量,永远不会被删除。

标签: python


【解决方案1】:

函数内的常量来自函数代码对象的co_consts属性。

>>> f.__code__.co_consts
(None, 40000)
>>> id(f.__code__.co_consts[1])
140572403241776
>>> f()
140572374132688
140572403241776

所以第二个int 对象的值为40000也是在函数定义中创建的,而不是在函数调用期间。

这是一个 CPython 实现细节,因为所有关于 CPython 字节码和代码对象的细节都是 CPython 实现细节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 2016-02-08
    • 1970-01-01
    • 2022-09-24
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多