首页 > 解决方案 > Python中嵌套函数的内存地址

问题描述

我一直明白,在 Python 中使用嵌套函数时,声明的内部函数是在封闭函数调用期间创建的,而在封闭函数返回时,本地范围内的所有名称都将被销毁。

例如,从这篇 Real Python 文章中

[本地范围]是在函数调用时创建的,而不是在函数定义时创建的,因此您将拥有与函数调用一样多的不同本地范围。即使您多次或递归调用同一个函数也是如此。每次调用都会创建一个新的本地范围。

所以每次调用封闭函数都应该为声明的嵌套函数产生一个新的内存地址,对吧?

def normal_function():
    def locally_scoped_function():
        pass

    print(locally_scoped_function)

normal_function() # <function normal_function.<locals>.locally_scoped_function at 0x109867670>
normal_function() # <function normal_function.<locals>.locally_scoped_function at 0x109867670>
normal_function() # <function normal_function.<locals>.locally_scoped_function at 0x109867670>

为什么地址是locally_scoped_function静态的?由于每次调用都normal_function应该重新声明和重新创建函数定义,所以不应该将它存储在内存中的不同插槽中吗?我希望打印出来的每一行都有不同的内存地址。

似乎我错过了一些非常明显的东西。我确实尝试在 StackOverflow 上寻找这个,但令人惊讶的是我无法找到关于这个特定问题的答案。

标签: python

解决方案


正如@Klaus D. 在评论中所建议的那样 - 当函数被垃圾收集时,很可能下一个创建的函数实例将分配在同一地址中。我们通过一个简单的实验证明这一点

def normal_function():
    def locally_scoped_function():
        pass
    print(locally_scoped_function)
    return locally_scoped_function

# Run as before
for i in range(3):
  normal_function()

# As before, all instances are created at the same address
<function normal_function.<locals>.locally_scoped_function at 0x7f173835f9d8>
<function normal_function.<locals>.locally_scoped_function at 0x7f173835f9d8>
<function normal_function.<locals>.locally_scoped_function at 0x7f173835f9d8>

# Let's save the created instances to avoid garbage collection
collect_to_avoid_gc = []
for i in range(3):
  collect_to_avoid_gc.append(
    normal_function()      
  )

# And indeed we'll see different addresses!
<function normal_function.<locals>.locally_scoped_function at 0x7f1737a32158>
<function normal_function.<locals>.locally_scoped_function at 0x7f1737a32378>
<function normal_function.<locals>.locally_scoped_function at 0x7f1737a32510>

推荐阅读