2016-08-29 12 views
17

Tại sao list(next(iter(())) for _ in range(1)) trả lại danh sách trống thay vì nâng cao StopIteration?Tại sao danh sách (tiếp theo (lặp (())) cho _ trong phạm vi (1)) == []?

>>> next(iter(())) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> [next(iter(())) for _ in range(1)] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> list(next(iter(())) for _ in range(1)) # ?! 
[] 

Điều tương tự cũng xảy ra với một chức năng tùy chỉnh mà tăng một cách rõ ràng StopIteration:

>>> def x(): 
...  raise StopIteration 
... 
>>> x() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in x 
StopIteration 
>>> [x() for _ in range(1)] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in x 
StopIteration 
>>> list(x() for _ in range(1)) # ?! 
[] 
+1

Wow, tôi thực sự thích câu trả lời trong câu hỏi "trùng lặp" gốc! – wheaties

+3

Đây là lỗi, nó đang được giải quyết với [PEP 479] (http://legacy.python.org/dev/peps/pep-0479/) trong đó 'StopIteration' sẽ được chuyển đổi thành' RuntimeError' để danh sách không dừng lặp lại không chính xác như bạn mong đợi. –

+1

@ TadhgMcDonald-Jensen vui lòng cho câu trả lời đó để tôi có thể bỏ phiếu. – wheaties

Trả lời

9

giả sử mọi thứ suôn sẻ, việc hiểu máy phát x() for _ in range(1) sẽ tăng StopIteration khi kết thúc lặp lại trên range(1) để cho biết rằng không còn mục nào khác để đưa vào danh sách.

Tuy nhiên vì x() tăng StopIteration nó kết thúc lên thoát khỏi ý nghĩa đầu hành vi này là một lỗi trong trăn đang được giải quyết bằng PEP 479

Trong python 3.6 hoặc sử dụng from __future__ import generator_stop trong python 3.5 khi một StopIteration truyền ra xa hơn nó được chuyển đổi vào một số RuntimeError để list không đăng ký nó khi kết thúc việc hiểu. Khi điều này có hiệu lực, lỗi có dạng như sau:

Traceback (most recent call last): 
    File "/Users/Tadhg/Documents/codes/test.py", line 6, in <genexpr> 
    stuff = list(x() for _ in range(1)) 
    File "/Users/Tadhg/Documents/codes/test.py", line 4, in x 
    raise StopIteration 
StopIteration 

The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
    File "/Users/Tadhg/Documents/codes/test.py", line 6, in <module> 
    stuff = list(x() for _ in range(1)) 
RuntimeError: generator raised StopIteration 
6

Ngoại lệ StopIteration được sử dụng để nói về cơ chế cơ bản của list chức năng khi để thực sự ngăn chặn lặp trên iterable rằng đã được truyền cho nó. Trong trường hợp của bạn, bạn đang nói với Python rằng thứ đã được chuyển vào list() là một máy phát điện. Vì vậy, khi nó được rằng, nó kết quả đầu ra một danh sách trống vì không có gì đã được tích lũy.

+0

Sai, lặp lại dừng từ 'cho _ trong phạm vi (1)' sẽ tăng 'StopIteration' cho danh sách để kết thúc nhưng nó không, thay vào đó' x() 'làm tăng một lỗi ** bị âm thầm * * khiến nó vô tình dừng lại. Điều này đang được thay đổi trong python3.6 và có thể được sử dụng với 'từ __future__ import generator_stop' trong python 3.5. xem [PEP 479] (http://legacy.python.org/dev/peps/pep-0479/) –

+2

@ TadhgMcDonald-Jensen Tôi rất vui khi thấy nó được sửa nhưng chỉ vì đó là một lỗi, không thay đổi thực tế rằng đó là chính xác những gì đang xảy ra. – wheaties

+0

@ TadhgMcDonald-Jensen Tôi sẽ không nói câu trả lời của lúa mì là sai. Tuy nhiên, nếu bạn có thể đăng bài đó như một câu trả lời, tôi sẵn sàng chấp nhận nó. –

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