Câu hỏi này là theo dõi trên a question about Python variable scope. Bạn có thể tìm thấy câu hỏi bổ sung q1, q2 và answers trên SO, thậm chí nhiều hơn nữa. Chính thức Python documentation và PEP 3104 có nghĩa vụ giải thích chi tiết, nhưng dường như chúng không hoàn toàn tự giải thích cho tôi.Nonlocal của Python phụ thuộc vào mức độ phân cấp?
Chủ đề tôi đang cố gắng giải quyết là tái cấu trúc mã có chứa nonlocal
/global
bằng cách di chuyển mã lên/xuống một cấp phân cấp.
Những gì tôi không hiểu là ý nghĩa của câu này từ tài liệu tham khảo Python:
Names listed in a nonlocal statement, unlike to those listed in a global statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously).
Với đoạn mã sau vào phạm vi toàn cầu:
var = 0
def outer():
global var # line A
var = 1
def inner():
nonlocal var # line B
var = 2
print('inner:', var)
inner()
print('outer:', var)
outer()
print('main:', var)
Thực hiện đặt ra một lỗi:
SyntaxError: no binding for nonlocal 'var' found
Mã hoạt động (với các ngữ nghĩa khác nhau, Dĩ nhiên, nếu một trong hai dòng A được nhận xét ra:
inner: 2
outer: 2
main: 0
hoặc dòng B là nhận xét ra:
inner: 2
outer: 1
main: 1
Tuy nhiên, trong ví dụ trên, và kể từ nonlocal
là nghĩa vụ để ràng buộc var cho " kèm theo phạm vi ", tôi đã có thể mong đợi rằng dòng A liên kết bên ngoài/var vào phạm vi toàn cầu và dòng B sau đó tìm bên ngoài/var và cũng rebinds bên trong/var để toàn cầu/var. Thay vào đó có vẻ như không tìm thấy nó ở tất cả (do rebinding trong dòng A, tôi giả sử) và đưa ra một lỗi.
Các kết quả mong muốn tôi mong đợi là:
inner: 2
outer: 2
main: 2
Đây có phải là ví dụ chỉ cần thêm một trong những trạng thái khó hiểu của tâm trí của Phạm vi bằng Python?
Hoặc, để làm điều này một câu hỏi mang tính xây dựng:
- Làm thế nào một ví dụ như vậy có thể được viết theo một cách mà nó không quan trọng mà tại đó mức một chức năng cư trú (có trao đổi
global
vớinonlocal
và ngược lại)? - Nếu các chức năng cư trú ở cấp bậc trung gian và không xác định, làm cách nào để tác giả của
outer()
thay đổi mã không ở mức ngoài cùng (trong trường hợp này), cũng không phải mức độinner()
phải được xúc động? -
Theo hiểu biết khiêm tốn của tôi về ngôn ngữ, việc xây dựng như thế này (phụ thuộc vào đóng cửa) chỉ cần tránh. Những người khác đã đề xuất sử dụng các tính năng ngôn ngữ khác (classes, func attrs) để đạt được loại độ nhạy ngữ cảnh này.
Biến toàn cục và cục bộ về cơ bản là khác nhau trong Python. Các câu lệnh 'nonlocal' chỉ có thể tham chiếu đến các biến cục bộ của một phạm vi kèm theo và không bao giờ đến các biến toàn cục - đó là cái' toàn cục' là sau cùng. Các khái niệm đằng sau 'global' và' nonlocal' khá khác nhau. Lập luận của bạn như thế nào hiện trạng nhà nước nên đặt ra một vấn đề được xây dựng hoàn toàn. Câu trả lời của tôi là: Không sử dụng các biến toàn cầu, và không sử dụng 'global', và tất cả các vấn đề" đã đề cập "(và một vài thứ nữa) sẽ biến mất. –
Mặc dù tôi thường đồng ý tránh sử dụng hình cầu, những người khác dường như thấy khái niệm hữu ích đến nỗi Python cung cấp từ khóa 'global' và Py3k thậm chí còn thêm một' nonlocal'. Tôi đang cố gắng hiểu những tác động của việc sử dụng kết hợp của họ. – cfi
"... và Py3k thậm chí còn thêm một' nonlocal'. " 'nonlocal' có nghĩa là làm cho các bao đóng hữu ích hơn. Nó không liên quan đến các biến toàn cục. –