2012-04-22 5 views
12

Given:python: Làm thế nào để tôi chụp một biến được khai báo trong một phạm vi ngoài tổ tiên phi toàn cầu?

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

Làm thế nào tôi có thể làm cho h thấy biến x?

Cảm ơn.

EDIT

nên đã đề cập đến nó trước đó, tôi đang sử dụng Python 2.7.3

+0

có vẻ như hầu hết -global với tôi ... ý tưởng tồi? (nhưng vẫn còn câu hỏi tốt) – Shep

+0

@Shep: bạn muốn một x khác nhau cho mỗi f() gọi, do đó, một biến toàn cầu sẽ không làm. – EOL

Trả lời

11

Bạn có thể làm x một function attribute:

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

Ngoài ra, bằng Python 3, bạn có thể sử dụng từ khóa nonlocal.

+3

+1 Giải pháp hay. –

+3

Nếu bạn đính kèm nó vào 'g' hoặc' h', bạn sẽ nhận được một 'x' riêng biệt cho mỗi cuộc gọi đến' f' chứ không phải là toàn cục có phạm vi 'f' và do đó có thể là toàn cầu. Điều đó đặc biệt quan trọng nếu 'g' hoặc' h' kết thúc dưới dạng đóng cửa (thậm chí gián tiếp, ví dụ: bằng cách được thêm làm gọi lại). – delnan

5

Nếu bạn đang sử dụng Python 3, bạn sử dụng từ khóa nonlocal. Đặt nonlocal x vào đầu hàm h. Nếu bạn đang sử dụng Python 2.x, một cách giải quyết là làm x một danh sách với một yếu tố, do đó bạn có thể sửa đổi nó:

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

f() 
4

Trong Python 3 chỉ cần sử dụng nonlocal:

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

Chỉ hoạt động trong Python 3 – jamylak

+0

bằng cách sử dụng print() có nghĩa là OP chỉ sử dụng python 3.x. –

+0

Điều đáng nói đến. Nhưng 'print()' với một đối số thực sự hoạt động trên python 2 mặc dù tôi cũng đồng ý rằng anh ta đang sử dụng python 3. – jamylak

0

chúng ta không thể đặt x như các đối số chức năng như workaround

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

f() 
0

dễ nhất là sử dụng một dict hoặc lớp rỗng, ví dụ:

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 

Mặc dù nhiều giải pháp tốt đã được cung cấp, thứ ey có trường hợp góc:

  • không cục bộ, mỗi Ashwini, là Python 3.x chỉ
  • chức năng thuộc tính, mỗi ovgolovin, sẽ thất bại được f được xác định lại và sau này được gọi bằng cách tham khảo