2014-05-04 18 views
5

Từ Python FAQ, chúng ta có thể đọc:Python: Tại sao nói rằng các biến chỉ được tham chiếu hoàn toàn toàn cầu?

Trong Python, các biến mà chỉ tham chiếu bên trong một hàm là ngầm toàn cầu

Và từ Python Tutorial on defining functions, chúng ta có thể đọc:

Việc thực hiện một hàm giới thiệu một bảng biểu tượng mới được sử dụng cho các biến cục bộ của hàm. Chính xác hơn, tất cả các phép gán biến trong một hàm lưu trữ giá trị trong bảng biểu tượng cục bộ; trong khi các tham chiếu biến đầu tiên tìm trong bảng biểu tượng cục bộ, sau đó trong bảng biểu tượng địa phương của các hàm bao quanh, sau đó trong bảng ký hiệu toàn cầu, và cuối cùng trong bảng có sẵn tên

Bây giờ tôi hoàn toàn hiểu hướng dẫn báo cáo, nhưng sau đó nói rằng variables that are only referenced inside a function are implicitly global có vẻ khá mơ hồ với tôi.

Tại sao nói rằng chúng hoàn toàn toàn cầu nếu chúng ta thực sự bắt đầu xem xét các bảng biểu tượng địa phương, và sau đó làm theo với các biểu tượng 'chung' hơn? Nó chỉ là một cách để nói rằng nếu bạn chỉ sẽ tham khảo một biến trong một hàm, bạn không cần phải lo lắng nếu nó là địa phương hoặc global?

Trả lời

7

Ví dụ

(Xem thêm xuống cho một bản tóm tắt)

Điều này có nghĩa là nếu một biến được không bao giờ giao cho trong cơ thể của một chức năng, sau đó nó sẽ được coi như toàn cầu.

Điều này giải thích lý do tại sao các công trình sau đây (a được coi là toàn cầu):

a = 1 

def fn(): 
    print a # This is "referencing a variable" == "reading its value" 

# Prints: 1 

Tuy nhiên, nếu biến được gán cho nơi nào đó trong cơ thể của chức năng, sau đó nó sẽ được coi như địa phương cho toàn bộ nội dung chức năng.

Điều này bao gồm các phát biểu được tìm thấy trước khi được gán cho (xem ví dụ bên dưới).

Điều này giải thích lý do tại sao các công việc sau đây không hoạt động. Ở đây, a được coi là địa phương,

a = 1 

def fn(): 
    print a 
    a = 2 # <<< We're adding this 

fn() 

# Throws: UnboundLocalError: local variable 'a' referenced before assignment 

Bạn có thể có Python đối xử với một biến như toàn cầu với tuyên bố global a. Nếu bạn làm như vậy, thì biến đó sẽ được coi là toàn cục, một lần nữa cho toàn bộ phần thân hàm.

a = 1 

def fn(): 
    global a # <<< We're adding this 
    print a 
    a = 2 

fn() 
print a 

# Prints: 1 
# Then, prints: 2 (a changed in the global scope too) 

Tóm tắt

Không giống như những gì bạn có thể mong đợi, Python sẽ không mùa thu trở lại phạm vi toàn cầu nếu không tìm thấy a trong phạm vi địa phương.

Điều này có nghĩa là một biến là địa phương hoặc toàn cầu cho toàn bộ nội dung chức năng: không thể toàn cầu và sau đó trở thành cục bộ.

Bây giờ, để biết một biến được coi là cục bộ hay toàn cầu, Python tuân thủ quy tắc sau. Biến là:

  • toàn cầu nếu chỉ tham chiếu và không bao giờ giao cho
  • toàn cầu nếu báo cáo kết quả global được sử dụng
  • địa phương nếu biến được gán cho ít nhất một lần (và global không được sử dụng)

ghi chú Hơn nữa

Trong thực tế, "implic itly toàn cầu "không thực sự có nghĩa là toàn cầu. Đây là một cách tốt hơn để suy nghĩ về nó:

  • "địa phương" có nghĩa là "ở đâu đó bên trong hàm"
  • "toàn cầu" thực sự có nghĩa là "ở đâu đó ngoài chức năng"

Vì vậy, nếu một biến là "ngầm toàn cầu" (== "ngoài chức năng"), sau đó nó "kèm theo phạm vi" sẽ được nhìn lên đầu tiên:

a = 25 

def enclosing(): 
    a = 2 
    def enclosed(): 
     print a 
    enclosed() 

enclosing() 

# Prints 2, as supplied in the enclosing scope, instead of 25 (found in the global scope) 

Bây giờ, như thường lệ, global cho phép bạn tham khảo các sc toàn cầu ope.

a = 25 

def enclosing(): 
    a = 2 
    def enclosed(): 
     global a # <<< We're adding this 
     print a 
    enclosed() 

enclosing() 

# Prints 25, as supplied in the global scope 

Bây giờ, nếu bạn cần thiết để gán cho a trong enclosed, và muốn a 's giá trị được thay đổi trong enclosing' phạm vi s, nhưng không phải trong phạm vi toàn cầu, sau đó bạn sẽ cần nonlocal, đó là mới trong Python 3. Trong Python 2, bạn không thể.

1

Đề án phân giải tên của Python đôi khi được gọi là quy tắc LEGB, sau phạm vi tên.

Khi bạn sử dụng một cái tên không đủ tiêu chuẩn bên trong một hàm, Python tìm kiếm lên đến bốn phạm vi-địa phương (L) phạm vi, sau đó phạm vi địa phương của bất kỳ kèm theo (E) defs và lambdas thì phạm vi toàn cầu (G) và sau đó được xây dựng trong phạm vi (B) — và dừng lại ở nơi đầu tiên được tìm thấy. Nếu tên không được tìm thấy trong quá trình tìm kiếm này, Python báo cáo lỗi.

  • Chỉ định tên tạo hoặc thay đổi tên địa phương theo mặc định.
  • Tham khảo tên tìm kiếm tại hầu hết bốn phạm vi: địa phương, sau đó kèm theo các chức năng (nếu có), sau đó toàn cầu, sau đó được tích hợp sẵn.
  • Tên được khai báo trong bảng sao kê toàn cầu và phi địa phương được gán tên để kèm theo phạm vi mô-đun và chức năng tương ứng.

Nói cách khác, tất cả các tên được gán bên trong hàm def tuyên bố (hoặc lambda) là theo mặc định. Các hàm có thể tự do sử dụng các tên được gán trong các hàm kèm theo cú pháp và phạm vi toàn cục, nhưng chúng phải khai báo chẳng hạn nonlocalsglobals để thay đổi chúng.

tham khảo: http://goo.gl/woLW0F

+2

Thiếu phân bổ: [Học Python: Lập trình hướng đối tượng mạnh mẽ] (http://goo.gl/woLW0F) –

+0

@A श wini च haudhary Xong :) – ajkumar25

1

Đây là khó hiểu và các tài liệu có thể đứng được rõ ràng hơn.

"được tham chiếu" trong ngữ cảnh này có nghĩa là tên không được chỉ định nhưng chỉ đọc từ đó. Ví dụ: trong khi a = 1 được gán cho a, print(a) (cú pháp Python 3) tham chiếu a mà không có bất kỳ chuyển nhượng nào.

Nếu bạn tham chiếua như trên mà không có bất kỳ chuyển nhượng nào, thì trình thông dịch Python tìm kiếm không gian tên mẹ của không gian tên hiện tại, đệ quy cho đến khi nó đạt đến không gian tên chung.

Mặt khác, nếu bạn gán cho biến, biến đó chỉ được xác định bên trong không gian tên cục bộ trừ khi được khai báo khác với từ khóa global. Vì vậy, a = 1 tạo tên mới, a, bên trong không gian tên cục bộ. Điều này được ưu tiên hơn bất kỳ biến số nào khác có tên là a trong các không gian tên cao hơn.

1

Không giống như một số ngôn ngữ khác, Python không tìm kiếm tên biến trong bảng biểu tượng cục bộ và sau đó quay lại để tìm kiếm trong phạm vi lớn hơn nếu không tìm thấy ở đó. Các biến được xác định là cục bộ tại thời gian biên dịch, không phải lúc chạy, bằng cách được gán cho (bao gồm cả được truyền vào như một tham số). Bất kỳ tên nào không được gán cho (và không được khai báo một cách rõ ràng toàn cầu) được coi là toàn cục và sẽ chỉ được tìm kiếm trong không gian tên chung. Điều này cho phép Python tối ưu hóa truy cập biến cục bộ (sử dụng bytecode LOAD_FAST), đó là lý do tại sao người dân địa phương nhanh hơn.

Có một số nếp nhăn liên quan đến bao đóng (và bằng Python 3, nonlocal) nhưng đó là trường hợp chung.

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