python - 当定义函数但未调用函数时,Python 解释器会解析变量引用吗?

标签 python function garbage-collection

首先,this post根本不回答我的问题或给我任何指导来回答我的问题。

我的问题是关于解析非局部变量的机制函数。

代码

# code block 1
def func():
    vals = [0, 0, 0]
    other_vals = [7, 8, 9]
    other = 12

    def func1():
        vals[1] += 1
        print(vals)

    def func2():
        vals[2] += 2
        print vals

    return (func1, func2)

f1, f2 = func()

尝试运行f1f2:

>>> f1()
[0, 1, 0]
>>> f2
[0, 1, 2]

这表明之前由 vals 引用的对象由 f1f2 共享,并且在执行 后不会被垃圾回收函数

other_valsother 引用的对象会被垃圾回收吗?我想是这样。但是 Python 如何决定不对 vals 进行垃圾回收呢?

假设1

Python 解释器将解析 func1func2 中的变量名称,以找出函数内部的引用,并增加 [0, 0, 0 的引用计数] 减 1,防止在 func 调用后进行垃圾回收。

但如果我这样做

# code block 2
def outerfunc():
    def innerfunc():
        print(non_existent_variable)
f = outerfunc()

没有报告错误。更多内容

# code block 3
def my_func():
    print(yet_to_define)
yet_to_define = "hello"

有效。

假设2 变量名称在运行时动态解析。这使得代码块 2 和 3 中的观察结果很容易解释,但是解释器如何知道它需要增加代码块 1 中 [0, 0, 0] 的引用计数?

哪个假设是正确的?

最佳答案

您的第一个示例创建了 closure ;另请参阅 Why aren't python nested functions called closures? , Can you explain closures (as they relate to Python)? ,和 What exactly is contained within a obj.__closure__? .

闭包机制确保解释器在返回的函数对象func1func2中存储对vals的引用。您的假设 1 是正确的:当 func 返回时,该引用会阻止 vals 被垃圾回收。

在您的第二个示例中,解释器无法在封闭范围中看到对 non_existent_variable 的引用,但这没关系,因为您的假设 2 也是正确的,因此您可以自由使用名称在函数声明时尚未绑定(bind)到对象,只要名称在实际调用函数时位于范围内即可。

“解释器如何知道需要增加代码块 1 中 [0, 0, 0] 的引用计数?”的答案?闭包机制是解释器在执行函数定义时(即,当它从脚本中的函数定义创建函数对象时)执行的显式操作。

每个 Python 函数对象(普通的 def 样式函数和 lambda )都有一个属性来存储此闭包信息,Python 2 和 Python 之间存在细微差别3. 有关详细信息,请参阅本答案开头的链接,但我将在这里提到 Python 3 提供了 nonlocal 关键字,其工作方式有点类似于 global 关键字: nonlocal 允许您对封闭的简单变量进行赋值; J.F. Sebastian's answer有一个简单的示例说明了nonlocal的使用。

请注意,对于嵌套函数,每次调用外部函数时都会处理内部函数定义,这允许您执行以下操作:

def func(vals):
    def func1():
        vals[1] += 1
        print(vals)

    def func2():
        vals[2] += 2
        print(vals)

    return func1, func2

f1, f2 = func([0, 0, 0])
f1()
f2()

f1, f2 = func([10, 20, 30])
f1()
f2()

输出

[0, 1, 0]
[0, 1, 2]
[10, 21, 30]
[10, 21, 32]

关于python - 当定义函数但未调用函数时,Python 解释器会解析变量引用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34367888/

相关文章:

python - 在所有 Pandas DataFrame 列中搜索字符串并过滤

python - 如何使对象出现在窗口边框的开头(或结尾)(使用pygame)

python - 在 selenium 中使用 python 循环

javascript - jQuery/JavaScript - 在一个函数完成后启动一个函数?

当函数作为参数传递时,Javascript 函数提升不适用?

Javascript GC 应用现有对象

c# - Xamarin.iOS 在将 C# 编译为 native 代码时如何处理内存管理?

Python psycopg2 在 postgresql 表的某些行中插入 NULL

ios - 从类文件初始化委托(delegate)

perl - 打开最新的日志文件并打印晚于特定时间戳的行