2012-04-22 32 views
12

Dane:python: Jak przechwycić zmienną zadeklarowaną w pozaglobalnym rodowodzie zewnętrznym?

def f(): 
    x = 0 
    def g(): 
     h() 
    def h(): 
     x += 1 
     print(x) 
    g() 

>>> f() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 8, in f 
    File "<stdin>", line 4, in g 
    File "<stdin>", line 6, in h 
UnboundLocalError: local variable 'x' referenced before assignment 
>>> 

Jak mogę dokonać h zobaczyć zmienną x?

Dzięki.

EDIT

Powinienem wymienić go wcześniej, używam Python 2.7.3

+0

wydaje się niemal -global do mnie ... zły pomysł? (ale wciąż dobre pytanie) – Shep

+0

@Shep: chcesz mieć inne x dla każdego wywołania f(), więc zmienna globalna by tego nie zrobiła. – EOL

Odpowiedz

11

Można dokonać x się function attribute:

def f(): 
    f.x = 0 
    def g(): 
     h() 
    def h(): 
     f.x += 1 
     print(f.x) 
    g() 

także od Pythona 3 można użyć słowa kluczowego nonlocal.

+3

+1 Ładne rozwiązanie. –

+3

Jeśli podłączysz go do 'g' lub' h', otrzymasz oddzielne 'x' dla każdego połączenia na' f', a nie globalne, które ma zakresy jako 'f', a więc prawdopodobnie globalne. Jest to szczególnie ważne, gdy 'g' lub' h' kończy się jako zamknięcie (nawet pośrednio, np. Przez dodanie jako wywołania zwrotnego). – delnan

5

Jeśli używasz Python 3, należy użyć słowa kluczowego nonlocal. Umieść nonlocal x na początku funkcji h. Jeśli używasz Pythona 2.x, obejście czyni x lista z jednego elementu, dzięki czemu można go zmodyfikować:

def f(): 
    x = [0] 
    def g(): 
     h() 
    def h(): 
     x[0] += 1 
     print x[0] 
    g() 

f() 
4

W Pythonie 3 wystarczy użyć nonlocal:

def f(): 
    x = 0 
    def g(): 
     h() 
    def h(): 
     nonlocal x 
     x += 1 
     print(x) 
    g() 
f() 
+1

Działa tylko w Pythonie 3 – jamylak

+0

używa print() oznacza, że ​​OP używa tylko Pythona 3.x. –

+0

Warto wspomnieć. Ale 'print()' z jednym argumentem faktycznie działa na pythonie 2, chociaż zgadzam się również, że używa on pythona 3. – jamylak

0

nie możemy umieścić x jako argumentów funkcji jako obejście

def f(): 
    x = 0 
    def g(): 
     h(x) 
    def h(x): 
     x += 1 
     print(x) 
    g() 

f() 
0

Najprostszym jest użycie dict lub pustą klasę, np:

class Empty: 
    x = 0 

def f(): 
    closure1 = dict(x=0) 
    closure2 = Empty() 
    def g(): h(x) 
    def h(x): 
     closure1["x"] += 1 
     closure2.x += 1 
    g() 
    print closure1["x"], closure2.x 

Chociaż wiele dobrych rozwiązań już dostarczono, ey mają przypadki róg:

  • nielokalnych, za Ashwini jest Python 3.x tylko
  • atrybut funkcja, za ovgolovin, zawiedzie się f jest nowo i później nazywany przez odniesienie
Powiązane problemy