2012-11-19 29 views
11

To działa zgodnie z oczekiwaniamiDlaczego nie mogę użyć `import *` w funkcji?

def outer_func(): 
    from time import * 

    print time() 

outer_func() 

mogę definiować funkcje zagnieżdżone w grzywny kontekstowego i nazywają je od innych zagnieżdżonych funkcji:

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

    def inner_func(): 
     print time() 

    inner_func() 

outer_func() 

mogę nawet importować poszczególne funkcje:

def outer_func(): 
    from time import time 

    def inner_func(): 
     print time() 

    inner_func() 

outer_func() 

To jednak rzuca 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() 

Mam świadomość, że to nie jest najlepsza praktyka, ale dlaczego to nie działa?

+1

ciekawe pytanie ... – mgilson

+0

"Działa to zgodnie z oczekiwaniami" - w jakiej wersji python? – georg

+0

@ thg435 Python 2. Python 3 jest bardziej rygorystyczny i odrzuca pierwszy przykład z 'SyntaxError: import * dozwolony tylko na poziomie modułu'. Dodałem tag python-2.x, aby wyjaśnić. –

Odpowiedz

22

Kompilator nie ma możliwości sprawdzenia, czy moduł czasu eksportuje obiekty o nazwie time.

Wolne zmienne zagnieżdżonych funkcji są powiązane z komórkami zamykającymi w czasie kompilacji. Same komórki zamykające wskazują na (lokalne) zmienne zdefiniowane w skompilowanym kodzie, w przeciwieństwie do globali, które w ogóle nie są powiązane. Zobacz python data model; funkcje odnoszą się do ich globali poprzez atrybut func_globals, a atrybut func_closure zawiera sekwencję komórek zamykających (lub None).

W związku z tym nie można użyć dynamicznej instrukcji importu w zakresie zagnieżdżonym.

I dlaczego funkcje zagnieżdżone potrzebują w ogóle komórek zamykających? Bo trzeba mechanizm odnoszący się do zmiennych lokalnych funkcji, gdy sama funkcja zakończyła:

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

afunc = foo('eggs') 

Dzwoniąc foo() Zdobyłem zagnieżdżonej funkcji, która odnosi się do zmiennej lunetą i kompilator musi utworzyć niezbędne referencje tłumacza, aby móc ponownie pobrać zmienną o ustalonym zakresie. Stąd komórki i ograniczenia na nich nałożone.

Powiązane problemy