2012-04-22 2 views
12

Дано:python: Как захватить переменную, объявленную в не глобальном внешнем пространстве?

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 
>>> 

Как я могу сделать h видеть переменную x?

Спасибо.

EDIT

Если упоминать об этом раньше, я использую Python 2.7.3

+0

кажется, почти -круглый ко мне ... плохая идея? (но все еще хороший вопрос) – Shep

+0

@Shep: вам нужен другой x для каждого вызова f(), поэтому глобальная переменная не будет работать. – EOL

ответ

11

Вы можете сделать x в function attribute:

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

Кроме того, с Python 3, вы можете использовать ключевое слово nonlocal.

+3

+1 Хорошее решение. –

+3

Если вы прикрепляете его к 'g' или' h', вы получаете отдельный 'x' для каждого вызова' f', а не глобальный, который является областью действия как 'f' и, следовательно, вероятно глобальным. Это особенно важно, если 'g' или' h' заканчиваются закрытием (даже косвенно, например, путем добавления в качестве обратного вызова). – delnan

5

Если вы используете Python 3, используется nonlocal ключевое слово. Положите nonlocal x в начало функции h. Если вы используете Python 2.x, обходной путь делает x список с одним элементом, так что вы можете изменить его:

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

f() 
4

В Python 3 просто использовать nonlocal:

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

Работает только в Python 3 – jamylak

+0

Он использует print() означает, что OP использует только python 3.x. –

+0

Стоит упомянуть. Но 'print()' с одним аргументом фактически работает на python 2, хотя я также согласен, что он использует python 3. – jamylak

0

Мы не можем ставить x в качестве аргументов функции в качестве временного решения

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

f() 
0

Проще всего использовать Dict или пустой класс, например:

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 

Хотя многие хорошие решения уже были предоставлены, еу имеют угловые случаи:

  • нелокальные, в Ашвини, является Python 3.x только
  • атрибут функции, в ovgolovin, потерпит неудачу в f переопределяется и позже названный по ссылке
Смежные вопросы