2012-05-12 36 views
12

Đoạn mã sau có thực thi xấu không?Liệu python chính thức hỗ trợ tái sử dụng một biến vòng lặp sau khi vòng lặp?

for i in some_values: 
    do_whatever(i) 
do_more_things(i) 

Bằng cách nào đó, cảm giác với tôi giống như biến số i phải nằm trong phạm vi chặn bên trong vòng lặp. Tuy nhiên python 2,7 cho phép tôi sử dụng lại nó sau vòng lặp.

Python có chính thức hỗ trợ tính năng đó hoặc tôi có lạm dụng ngôn ngữ không?

+0

hmmm ... có vẻ như điều này có thể ok vì nó được sử dụng [ở đây] (http://stackoverflow.com/số câu hỏi/2138873/cleanest-way-to-get-last-item-từ-python-iterator) – jamylak

+1

Có một số lượng hợp lý các trường hợp sử dụng được hưởng lợi từ việc truy cập giá trị cuối cùng của biến vòng lặp trong mã tiếp theo –

Trả lời

12

Vâng, nó chính thức:

for_stmt ::= "for" target_list "in" expression_list ":" suite 
       ["else" ":" suite] 

> The target list is not deleted when the loop is finished 

http://docs.python.org/reference/compound_stmts.html#for

Lưu ý rằng một target list sau for là nhiều hơn so với chỉ một biến:

for some_list[blah] in... 
for some_object.foo in... 
for a[:n] in ...: 

vv Những điều này có thể không chỉ đơn giản biến mất sau vòng lặp.

0

Đó không phải là một tính năng. Khi bạn viết biến còn lại trong phạm vi. Đó là hành vi thông dịch bình thường.

+2

Hmm, Tôi downvoted điều này bởi vì "Đó không phải là một tính năng" có vẻ mâu thuẫn với câu trả lời hàng đầu, nhưng bây giờ đọc lại câu hỏi tôi nghĩ bạn có nghĩa là "nó không phải là một tính năng mà' i' chỉ kéo dài trong phạm vi vòng lặp ".Mặc dù vậy, tôi sẽ để lại lời bình luận, bởi vì tôi nghĩ rằng từ ngữ của bạn không rõ ràng và cách diễn giải đầu tiên của tôi là cái tự nhiên hơn (và sai). –

3

Python có thể cảm thấy hơi đặc biệt khi nói đến phạm vi nếu bạn đến từ các ngôn ngữ như C hoặc Java. Như câu trả lời trước đó cho biết, mã này là hoàn toàn hợp lệ nhưng tôi sẽ khuyên bạn nên chống lại nó. Nó tạo ra mã không thể đọc được, và hơn nữa, nếu some_values hóa ra là trống, sẽ có một ngoại lệ được nâng lên trên dòng cuối cùng của mã.

Vì vậy, câu trả lời cho câu hỏi của bạn là - có, nó được hỗ trợ chính thức nhưng trong hầu hết các trường hợp, chiến lược không được đề xuất.

Thảo luận thú vị có thể được tìm thấy here và thảo luận địa phương về SO.

+0

Ai không đề xuất? Và tại sao nó làm cho mã khó đọc - các biến python tồn tại trong phạm vi của chúng, tuy nhiên chúng được giới thiệu. – Marcin

+0

Tôi đồng ý. Nó chỉ cảm thấy "bẩn". – georg

+2

Trước hết, tôi tin rằng nó làm cho một giả định rằng vòng lặp được chạy và biến thực sự được gán. Thứ hai, khi đọc này như là một người thứ ba, tôi sẽ giả định các biến được xác định trên cùng một/thấp hơn thụt lề. Nhưng cộng đồng python được chia cho cái này. – petr

1

Giống như @petr đã nói, nó có vẻ không tự nhiên. Không phải vì nó cho phép nó tự nhiên hoặc bạn phải sử dụng nó.

Tôi thà có một cái gì đó như thế này, mặc dù nó có thể không áp dụng đối với logic với một break use-case:

for i in some_values: 
    do_whatever(i) 
else: 
    do_more_things(i)

Nhưng điều này vẫn tăng NameError nếu some_values đánh giá để trống, nhưng âm thanh rõ ràng hơn. Nó không cung cấp cho khả năng đọc rõ ràng của một phạm vi bên trong nhưng thụt đầu dòng có thể gợi ý nó.

Nhưng như đã nói, để trả lời cho câu hỏi cụ thể của OP, có, nó hợp pháp.

2

Bạn có thể sử dụng kỹ thuật này để quét một danh sách cho mục thoả mãn một số tiêu chí:

for item in iter: 
    if interesting(item): 
     break 
else: 
    raise ValueError('iter is boring.') 

handle(item) 
Các vấn đề liên quan