为什么我不能在函数中使用 `import *`?

15

这个按预期工作。

def outer_func():
    from time import *

    print time()

outer_func()

我可以在上下文中定义嵌套函数,并从其他嵌套函数中调用它们:

def outer_func():
    def time():
        return '123456'

    def inner_func():
        print time()

    inner_func()

outer_func()

我甚至可以导入单个函数:

def outer_func():
    from time import time

    def inner_func():
        print time()

    inner_func()

outer_func()

但是,这会抛出 SyntaxError:因为它包含具有自由变量的嵌套函数,所以在函数“outer_func”中不允许使用import *

def outer_func():
    from time import *

    def inner_func():
        print time()

    inner_func()

outer_func()

我知道这不是最佳实践,但为什么它不能工作?


这在哪个Python版本中按预期工作? - georg
@thg435 Python 2。Python 3 更加严格,拒绝第一个例子并显示 SyntaxError: import * only allowed at module level。我已经添加了 python-2.x 标签以澄清。 - Wilfred Hughes
@WilfredHughes:Python 2.6和2.7也拒绝运行它。 - georg
@thg435在Python 2.7下可以工作,但会有一个警告。nested2.py:1: SyntaxWarning: import * only allowed at module level\n def outer_func():\n1353343092.54 - Wilfred Hughes
@WilfredHughes:是的,这个警告就是我所说的“不起作用”;) - georg
1个回答

23

编译器无法知道 time 模块是否导出了名为 time 的对象。

嵌套函数的自由变量在编译时绑定到闭包单元。闭包单元本身指向编译代码中定义的(本地)变量,而不是全局变量,后者根本没有绑定。参见Python 数据模型;函数通过 func_globals 属性引用它们的全局变量,func_closure 属性保存一个闭包单元序列(或 None)。

因此,在嵌套作用域中不能使用动态导入语句。

那么,为什么嵌套函数需要闭包单元呢?因为当函数本身完成时,需要一种机制来引用局部函数变量:

def foo(spam):
    def bar():
        return spam
    return bar

afunc = foo('eggs')

通过调用 foo() 我获得了一个嵌套函数,它引用了一个作用域变量,编译器需要创建必要的引用以便解释器能够再次检索该作用域变量。因此出现了单元格,并且对其施加了限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接