2010-05-13 31 views
156

Tôi mới sử dụng Python, vì vậy đây có thể là một câu hỏi phạm vi đơn giản. Các mã sau đây trong một tập tin Python (mô-đun) là khó hiểu cho tôi một chút:Phạm vi của biến được khởi tạo trong câu lệnh if là gì?

if __name__ == '__main__': 
    x = 1 

print x 

Trong các ngôn ngữ khác mà tôi đã từng làm việc tại, mã này sẽ ném một ngoại lệ, như biến x là địa phương để báo cáo kết quả if và nên không tồn tại bên ngoài nó. Nhưng mã này thực thi và in 1. Có ai giải thích được hành vi này không? Tất cả các biến được tạo trong một mô-đun toàn cầu/có sẵn cho toàn bộ mô-đun?

+7

Một quirk khác bạn có thể không biết: nếu câu lệnh 'if' ở trên không giữ đúng (tức là' __name__' là * không * ''__main __'', ví dụ khi bạn nhập mô-đun thay vì thực thi nó cấp cao nhất), sau đó 'x' sẽ không bao giờ bị ràng buộc, và câu lệnh' print x' tiếp theo sẽ ném một 'NameError: name 'x' không được định nghĩa'. – Santa

Trả lời

155

Biến số Python được đưa vào phạm vi chức năng, lớp hoặc mô đun trong cùng mà chúng được chỉ định. Các khối điều khiển như các khối ifwhile không được tính, do đó, một biến được chỉ định bên trong một if vẫn được phạm vi đến một hàm, lớp hoặc mô-đun.

(chức năng Implicit xác định bởi một biểu hiện phát hoặc danh sách/thiết lập/dict hiểu làm đếm, cũng như biểu thức lambda. Bạn không thể nhét một câu lệnh gán vào bất kỳ của những người, nhưng thông số lambda và for mục tiêu khoản là chuyển nhượng ngầm.)

36

Vâng, họ đang ở trong "phạm vi địa phương" giống nhau, và thực sự mã như thế này là phổ biến trong Python:

if condition: 
    x = 'something' 
else: 
    x = 'something else' 

use(x) 

Lưu ý rằng x không được khai báo hoặc khởi trước tình trạng này, như nó sẽ trong C hoặc Java, chẳng hạn.

Nói cách khác, Python không có phạm vi cấp khối. Tuy nhiên, hãy cẩn thận với các ví dụ như

if False: 
    x = 3 
print(x) 

sẽ nêu rõ trường hợp ngoại lệ NameError.

1

Có. Nó cũng đúng với phạm vi for. Nhưng không phải chức năng của khóa học.

Trong ví dụ của bạn: nếu điều kiện trong tuyên bố if là sai, thì x sẽ không được xác định.

1

bạn đang thực thi mã này từ dòng lệnh do đó if điều kiện là đúng và x được đặt. Hãy so sánh:

>>> if False: 
    y = 42 


>>> y 
Traceback (most recent call last): 
    File "<pyshell#6>", line 1, in <module> 
    y 
NameError: name 'y' is not defined 
28

Scope trong python sau theo thứ tự:

  • Tìm kiếm phạm vi địa phương

  • Tìm kiếm phạm vi của bất kỳ chức năng kèm theo

  • Tìm kiếm phạm vi toàn cầu

  • Tìm kiếm tích hợp

(source)

ý rằng if và khác looping/cấu trúc phân nhánh không được liệt kê - chỉ lớp học, chức năng, và các module cung cấp phạm vi trong Python, vì vậy bất cứ điều gì đã tuyên bố trong một khối if có cùng phạm vi như bất cứ điều gì đã suy giảm bên ngoài khối. Các biến không được kiểm tra tại thời gian biên dịch, đó là lý do tại sao các ngôn ngữ khác lại ném một ngoại lệ. Trong python, miễn là biến tồn tại tại thời điểm bạn yêu cầu nó, không có ngoại lệ nào được ném ra.

5

Như Eli đã nói, Python không yêu cầu khai báo biến.Trong C, bạn có thể nói:

int x; 
if(something) 
    x = 1; 
else 
    x = 2; 

nhưng trong khai báo Python là ngầm, vì vậy khi bạn gán cho x nó sẽ tự động được khai báo. Đó là bởi vì Python được gõ động - nó sẽ không hoạt động trong một ngôn ngữ được gõ tĩnh, bởi vì phụ thuộc vào đường dẫn được sử dụng, một biến có thể được sử dụng mà không được khai báo. Điều này sẽ bị bắt tại thời gian biên dịch trong một ngôn ngữ được gõ tĩnh, nhưng với một ngôn ngữ được gõ động được phép.

Lý do duy nhất mà ngôn ngữ được nhập tĩnh được giới hạn là phải khai báo biến ngoài báo cáo if do sự cố này. Embrace năng động!

7

Không giống như các ngôn ngữ như C, một biến Python nằm trong phạm vi toàn bộ hàm (hoặc lớp hoặc mô-đun) xuất hiện, không chỉ trong "khối" bên trong. Nó giống như bạn đã khai báo int x ở trên cùng của hàm (hoặc lớp hoặc mô-đun), ngoại trừ trong Python bạn không phải khai báo biến.

Lưu ý rằng sự tồn tại của biến x chỉ được kiểm tra khi chạy - tức là khi bạn nhận được câu lệnh print x. Nếu __name__ không bằng "__main__" thì bạn sẽ nhận được ngoại lệ: NameError: name 'x' is not defined.

+0

Các lớp không tạo phạm vi; một biến "cục bộ" trong một lớp đơn giản được thêm vào dict của lớp khi tạo. – chepner

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