2013-02-25 26 views
6

TL; DR: Tôi muốn một người dân địa phương() trông giống như một phạm vi có chứa.Người dân địa phương Python() để chứa phạm vi

Xin chào, tất cả.

Tôi đang dạy một khóa học về lập trình Python cho một số bạn bè hóa học và tôi muốn chắc chắn rằng tôi thực sự hiểu phạm vi.

xem xét:

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

Người dân địa phương in một môi trường trống rỗng, và globals in các globals bình thường. Làm cách nào để truy cập vào môi trường mà x được lưu trữ? Rõ ràng là thông dịch viên biết về nó vì tôi có thể tham khảo nó.

Liên quan: Khi nào phạm vi xảy ra? Tên sauĐược đặt trên a = x + 2 chỉ khi x = 3 được bao gồm:

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

Nếu bạn nhận xét x = 3, mã hoạt động. Điều này có nghĩa là python thực hiện một phạm vi từ vựng vượt qua mã trước khi nó diễn giải nó?

+0

bạn có cần danh sách không? bởi vì bạn chỉ có thể in x sau khi in hình cầu. EDIT: quên nói nếu bạn truy cập x với in x sau đó cũng là người dân địa phương() chứa đầy x: 1. –

+0

có thể trùng lặp của [Nhận người dân địa phương từ không gian tên gọi bằng Python] (http://stackoverflow.com/questions/6618795/get-locals-from-calling-namespace-in-python) – piokuc

Trả lời

0

Tuyên bố print(locals()) đề cập đến phạm vi bao quanh gần nhất, đó là hàm def b():. Khi gọi b(), bạn sẽ in người dân địa phương vào hàm b này và định nghĩa của x nằm ngoài phạm vi.

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

sẽ in x dưới dạng biến cục bộ.

Đối với câu hỏi thứ hai của bạn:

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

>>> a() 

mang đến cho không có lỗi.

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

>>> a() 

không có lỗi.

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

>>> a() 

cho lỗi sau: UnboundLocalError: local variable 'x' referenced before assignment

IMO (hãy kiểm tra), trong trường hợp thứ ba này, tuyên bố đầu tiên trong cơ thể của b() tìm kiếm giá trị của x trong phạm vi kèm theo nhất. Và trong phạm vi này, x được gán trên dòng tiếp theo. Nếu bạn chỉ có tuyên bố a = x+2, x không được tìm thấy trong phạm vi bao quanh nhất và được tìm thấy trong phạm vi bao quanh 'tiếp theo', với x = 1.

6

gì đang xảy ra trong mã của bạn là khi python thấy là dòng x=3 trong phương pháp b() của bạn, nó được tái x với một phạm vi trong b chức năng thay vì sử dụng x với nó là phạm vi trong a chức năng.

vì mã của bạn sau đó đi:

a = x+2 
    x = 3 

nó đang nói rằng bạn cần phải xác định khu vực nội scoped x trước khi tham khảo nó.Tuy nhiên,

tuy nhiên, khi bạn không có sự chỉ định x trong python b chức năng không cố gắng để làm cho một phạm vi thấp hơn x và sẽ không ném bất kỳ lỗi nào.

Đoạn mã dưới đây sẽ minh họa điều này:

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

    def c(): 
     print (x) 

    b() 
    c() 
    print (x) 

a() 

Tuy nhiên nếu bạn đã tuyên bố x như global bạn có thể sử dụng nó trong một chức năng, như vậy:

def a(): 
    global x 
    x = 1 

    def d(): 
     global x 
     x += 2 

    print (x) 
    d() 
    print (x) 

a() 

Python 3 cũng đã được thêm vào a nonlocal từ khóa sẽ cho phép bạn truy cập một biến từ phạm vi bao quanh, cách sử dụng giống như:

def a(): 
    x = 1 

    def d(): 
     nonlocal x 
     x += 2 

    print (x) 
    d() 
    print (x) 

a() 

Sẽ in kết quả giống như ví dụ global.


Trong trường hợp tôi nhớ đọc lại câu hỏi:

Theo câu trả lời cho Get locals from calling namespace in Python:

bạn có thể sử dụng:

import inspect 

def a(): 
    x = 1 

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

a() 

để có được phạm vi địa phương trong những chức năng người gọi.

+0

Có thể đáng chú ý là Python 3 đã được thêm vào một từ khóa 'nonlocal' mà bạn có thể sử dụng trong hàm bên trong để có thể rebind một tên hiện có từ một phạm vi kèm theo. – Blckknght

+0

Rất gợi cảm! chắc chắn đáng chú ý cảm ơn. – Serdalis

Các vấn đề liên quan