Подтвердить что ты не робот

Почему я не могу использовать `import *` в функции?

Это работает как ожидалось

def outer_func():
    from time import *

    print time()

outer_func()

Я могу определить вложенные функции в контексте fine и вызвать их из других вложенных функций:

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: import * is not allowed in function 'outer_func' because it contains a nested function with free variables:

def outer_func():
    from time import *

    def inner_func():
        print time()

    inner_func()

outer_func()

Я знаю, что это не лучшая практика, но почему она не работает?

4b9b3361

Ответ 1

У компилятора нет возможности узнать, экспортирует ли модуль времени объекты с именем time.

Свободные переменные вложенных функций привязаны к ячейкам закрытия во время компиляции. Ячейки Closure сами указывают на (локальные) переменные, определенные в скомпилированном коде, а не на глобальные, которые вообще не привязаны. См. модель данных python; функции ссылаются на их глобальные переменные с помощью атрибута func_globals, а атрибут func_closure содержит последовательность замыкающих ячеек (или None).

Таким образом, вы не можете использовать динамический оператор импорта во вложенной области.

А зачем вложенным функциям вообще нужны закрывающие ячейки? Поскольку вам нужен механизм для ссылки на локальные переменные функции, когда сама функция завершена:

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

afunc = foo('eggs')

Вызвав foo(), я получил вложенную функцию, которая ссылается на переменную с областью, и компилятор должен создать необходимые ссылки для интерпретатора, чтобы снова получить эту переменную области. Следовательно, ячейки и ограничения на них.