Tôi đang làm gì sai ở đây?UnboundLocalError trong Python
counter = 0
def increment():
counter += 1
increment()
Mã trên ném một số UnboundLocalError
.
Tôi đang làm gì sai ở đây?UnboundLocalError trong Python
counter = 0
def increment():
counter += 1
increment()
Mã trên ném một số UnboundLocalError
.
Python không có khai báo biến, vì vậy nó phải tìm ra các scope của các biến riêng của mình. Nó làm như vậy bằng một quy tắc đơn giản: Nếu có một phép gán cho một biến bên trong một hàm, biến đó được coi là cục bộ. [1] Như vậy, dòng
counter += 1
ngầm làm counter
địa phương để increment()
. Tuy nhiên, cố gắng thực hiện dòng này sẽ cố đọc giá trị của biến cục bộ counter
trước khi được gán, dẫn đến số UnboundLocalError
. [2]
Nếu counter
là biến toàn cục, từ khóa global
sẽ giúp ích. Nếu increment()
là hàm cục bộ và counter
biến cục bộ, bạn có thể sử dụng nonlocal
bằng Python 3.x.
python 3 tài liệu có [faq page về lý do tại sao-am-i-get-an-unboundlocalerror-khi-biến-giá-có-một-giá trị] (https://docs.python.org/3/faq/programming .html # why-am-i-get-an-unboundlocalerror-khi-the-biến-có-một-giá trị) qua [unboundlocalerror-local-variable-l-tham chiếu-trước-gán-python] (http: // stackoverflow.com/questions/21456739/unboundlocalerror-local-variable-l-referenced-before-assignment-python) – here
Một lưu ý đã bắt được tôi, tôi đã có một biến được khai báo ở đầu tệp mà tôi có thể đọc bên trong một hàm mà không có vấn đề, tuy nhiên để ghi vào một biến mà tôi đã tuyên bố ở trên cùng của tập tin, tôi đã phải sử dụng toàn cầu. – mouckatron
Để sửa đổi biến toàn cầu bên trong một hàm, bạn phải sử dụng từ khóa chung.
Khi bạn cố gắng để làm điều này mà không cần dòng
global counter
bên trong định nghĩa của tăng, một bộ đếm biến địa phương đặt tên được tạo ra để giữ cho bạn từ mucking lên biến truy cập rằng toàn bộ chương trình có thể phụ thuộc vào.
Lưu ý rằng bạn chỉ cần sử dụng toàn cầu khi bạn đang sửa đổi biến; bạn có thể đọc truy cập từ bên trong gia tăng mà không cần báo cáo toàn cầu.
Bạn cần phải sử dụng global statement để bạn được điều chỉnh bộ đếm biến toàn cầu, thay vì một biến địa phương:
counter = 0
def increment():
global counter
counter += 1
increment()
Nếu phạm vi kèm theo đó counter
được định nghĩa trong không phải là phạm vi toàn cầu, trên Python 3.x bạn có thể sử dụng nonlocal statement. Trong tình hình như vậy trên Python 2.x bạn sẽ không có cách nào để chỉ định lại tên không cục bộ counter
, vì vậy bạn sẽ cần phải thực hiện counter
có thể thay đổi và sửa đổi nó:
counter = [0]
def increment():
counter[0] += 1
increment()
print counter[0] # prints '1'
Cool .. Nó hoạt động +1 –
Nó hoạt động nhờ. –
thử này
counter = 0
def increment():
global counter
counter += 1
increment()
Python không hoàn toàn bị lốm đốm.
Xem này: Using global variables in a function other than the one that created them
và điều này: http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/
Trong khi liên kết này có thể trả lời câu hỏi, tốt hơn nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở thành không hợp lệ nếu trang được liên kết thay đổi. - [Từ đánh giá] (/ review/low-quality-posts/19036082) – munk
@munk Cool, bạn nhận ra rằng đây là một liên kết đến một câu trả lời khác trên SO? – Marcin
Python có phạm vi từ vựng theo mặc định, có nghĩa là mặc dù phạm vi kèm theo có thể truy cập các giá trị trong phạm vi kèm theo của nó, nó không thể sửa đổi chúng (trừ khi chúng được khai báo chung với từ khóa global
).
Đóng cửa liên kết giá trị trong môi trường bao quanh với tên trong môi trường cục bộ. Môi trường cục bộ sau đó có thể sử dụng giá trị bị ràng buộc, và thậm chí gán lại tên đó cho một cái gì đó khác, nhưng nó không thể sửa đổi ràng buộc trong môi trường kèm theo.
Trong trường hợp của bạn, bạn đang cố gắng xử lý counter
dưới dạng biến cục bộ chứ không phải giá trị bị ràng buộc. Lưu ý rằng đoạn mã này, mà liên kết với giá trị của x
giao trong môi trường kèm theo, hoạt động tốt:
>>> x = 1
>>> def f():
>>> return x
>>> f()
1
Để trả lời các câu hỏi trong dòng tiêu đề của bạn, * vâng, có đóng cửa bằng Python, ngoại trừ họ chỉ áp dụng bên trong một hàm, và cả (trong Python 2.x) chúng là chỉ đọc; bạn không thể liên kết lại tên với một đối tượng khác (mặc dù nếu đối tượng có thể thay đổi, bạn có thể sửa đổi nội dung của nó). Trong Python 3.x, bạn có thể sử dụng từ khóa nonlocal
để sửa đổi biến đóng.
def incrementer():
counter = 0
def increment():
nonlocal counter
counter += 1
return counter
return increment
increment = incrementer()
increment() # 1
increment() # 2
* Tiêu đề câu hỏi ban đầu được hỏi về đóng cửa bằng Python.
Lý do tại sao mã của bạn ném một số UnboundLocalError
đã được giải thích rõ trong các câu trả lời khác.
Nhưng có vẻ như với tôi rằng bạn đang cố gắng xây dựng thứ gì đó hoạt động như itertools.count()
.
Vậy tại sao bạn không thử nó ra và xem nếu nó phù hợp với trường hợp của bạn:
>>> from itertools import count
>>> counter = count(0)
>>> counter
count(0)
>>> next(counter)
0
>>> counter
count(1)
>>> next(counter)
1
>>> counter
count(2)
@ZeroPiraeus: tại sao bạn búa một câu hỏi với 40k xem +, đó là kết quả đầu tiên cho "UnboundLocalError" trong Google, là bản sao của một câu hỏi gần giống hệt nhau mà bạn đã trả lời thay vì chỉ đăng câu trả lời của bạn * ở đây *? – vaultah
Câu hỏi này và câu hỏi hiện đang được đánh dấu trùng lặp đang được thảo luận trong [Phòng chat Python] (http://chat.stackoverflow.com/transcript/message/34899645#34899645). –
Nhiều câu trả lời ở đây nói để sử dụng 'toàn cục', và mặc dù nó hoạt động, sử dụng các hình cầu có thể sửa đổi thường là _not_ khuyên dùng khi các tùy chọn khác tồn tại. –