2013-02-25 10 views
6

TL; DR: Chcę locals(), który wygląda w zawierający zakres.Python locals() dla zawierający zakres

Witam wszystkich.

Uczę kurs programowania w języku Python dla niektórych przyjaciół chemików i chcę mieć pewność, że naprawdę rozumiem zakres.

Rozważmy:

def a(): 
    x = 1 
    def b(): 
     print(locals()) 
     print(globals()) 
    b() 

Miejscowi drukuje pustą środowiska i globalne drukuje zwykle globalnych. Jak uzyskać dostęp do środowiska, w którym zapisano x? Oczywiście tłumacz o tym wie, bo mogę się do niego odnieść.

Powiązane: Kiedy ma miejsce ustalanie zakresu? Poniższe nameErrors na a = x + 2 tylko wtedy, gdy x = 3 jest wliczone:

def a(): 
    x = 1 
    def b(): 
     a = x+2 
     x = 3 
    b() 

Jeśli wykomentuj x = 3, kod działa. Czy to oznacza, że ​​pyton sprawia, że ​​leksykalny zakres przechodzi przez kod, zanim go zinterpretuje?

+0

Czy potrzebujesz listy? ponieważ możesz po prostu drukować x po wydrukowaniu globali. EDYCJA: zapomnij powiedzieć, jeśli masz dostęp do x z print x, to także locals() wypełnione x: 1. –

+0

możliwy duplikat [Uzyskaj locals z wywoływania przestrzeni nazw w Pythonie] (http://stackoverflow.com/questions/6618795/get-locals-from-calling-namespace-in-python) – piokuc

Odpowiedz

0

Oświadczenie print(locals()) odnosi się do najbliższego obejmującego zakresu, czyli funkcji def b():. Podczas wywoływania b(), wydrukujesz locals do tej funkcji b, a definicja x jest poza zakresem.

def a(): 
    x = 1 
    def b(): 
     print(locals()) 
     print(globals()) 
    b() 
    print(locals()) 

wydrukuje x jako zmienną lokalną.

Na drugie pytanie:

def a(): 
    x = 1 
    def b(): 
     #a = x+2 
     x = 3 
    b() 

>>> a() 

daje żadnego błędu.

def a(): 
    x = 1 
    def b(): 
     a = x+2 
     #x = 3 
    b() 

>>> a() 

nie daje żadnego błędu.

I

def a(): 
    x = 1 
    def b(): 
     a = x+2 
     x = 3 
    b() 

>>> a() 

daje następujący błąd: UnboundLocalError: local variable 'x' referenced before assignment

IMO (proszę sprawdzić), w tym trzecim przypadku, pierwsze pismo w ciele b() szuka wartości x w zakresie najbardziej okalającego. I w tym zakresie x jest przydzielany w następnym wierszu. Jeśli masz tylko instrukcję a = x+2, x nie zostanie znaleziony w najbardziej zbliżonym zakresie i znajduje się w "następnym" obejmującym zakres, z x = 1.

6

Co się dzieje w kodzie jest, że gdy python zobaczyć to linia w swojej metodzie b()x=3, jest odtworzenie x z zakresu wewnątrz funkcji b zamiast używania x z jego zakres w funkcji a.

ponieważ Twój kod następnie idzie:

a = x+2 
    x = 3 

jest powiedzenie, że trzeba zdefiniować wewnętrzna scoped x przed przedstawieniu go.

Jeśli jednak nie masz przypisania x w pytaniu o funkcję b, nie próbujesz utworzyć zakresu o mniejszej skali niż x i nie będzie zgłaszał żadnych błędów.

Poniższy kod będzie to zilustrować:

def a(): 
    x = 1 
    def b(): 
     x = 3 
     print (x) 

    def c(): 
     print (x) 

    b() 
    c() 
    print (x) 

a() 

Jednak jeśli były zadeklarować x jak global można go używać wewnątrz funkcji, tak jak poniżej:

def a(): 
    global x 
    x = 1 

    def d(): 
     global x 
     x += 2 

    print (x) 
    d() 
    print (x) 

a() 

Python 3 też dodanej słowo kluczowe, które umożliwia dostęp do zmiennej z otaczającego zakresu, użycie jest następujące:

def a(): 
    x = 1 

    def d(): 
     nonlocal x 
     x += 2 

    print (x) 
    d() 
    print (x) 

a() 

Wydrukuje takie same wyniki, jak przykład global.


w przypadku Tęsknię przeczytać pytanie:

Jak na odpowiedź na Get locals from calling namespace in Python:

można użyć:

import inspect 

def a(): 
    x = 1 

    def d(): 
     frame = inspect.currentframe() 
     try: 
      print (frame.f_back.f_locals) 
     finally: 
      del frame 
    d() 

a() 

aby uzyskać lokalny zakres funkcji gość.

+0

Warto zauważyć, że dodatek Python 3 został dodany słowo kluczowe "nielokalny", którego można użyć w funkcji wewnętrznej, aby móc ponownie powiązać istniejącą nazwę z otaczającym ją zakresem. – Blckknght

+0

Bardzo sexy! Wyzywająco warte zauważenia dzięki. – Serdalis

Powiązane problemy