2017-04-13 41 views
5

Có thể làm tổ tuyên bố yield from không?Tại sao lồng ghép "lãi suất từ" báo cáo (bộ tạo máy phát) tạo ra giá trị `None` kết thúc?

Các hình thức đơn giản là rõ ràng:

def try_yield1(): 
    x = range(3) 
    yield from x 

nào sản xuất:

0 
1 
2 

Nhưng nếu tôi đã lồng máy phát điện?

def try_yield_nested(): 
    x = [range(3) for _ in range(4)] 
    yield from ((yield from y) for y in x) 

này tạo ra:

0 
1 
2 
None # why? 
0 
1 
2 
None # ... 
0 
1 
2 
None # ... 

Tại sao nó sản xuất None nếu tôi sử dụng yield from (mặc dù nó là lồng nhau)?

Tôi biết tôi có thể làm điều gì đó như:

from itertools import chain 

def try_yield_nested_alternative(): 
    x = [range(3) for _ in range(4)] 
    yield from chain.from_iterable(x) 

nào tạo ra cùng một sản lượng bỏ đi None (đó là những gì tôi mong đợi). Tôi cũng có thể viết một vòng lặp đơn giản:

for x in [range(3) for _ in range(3)]: 
    yield from x 

Nhưng, tôi nghĩ rằng nó sẽ được nhiều hơn pythonic sử dụng đoàn lồng nhau (tốt thậm chí yield from x from y hoặc yield from x for x in y, nhưng đó không phải là cú pháp thích hợp). Tại sao nó không hoạt động như tôi mong đợi?

Trả lời

7

yield là một biểu thức, nó sẽ đánh giá bất cứ điều gì bạn send(value) nó. Đơn giản chỉ cần đặt, nếu bạn gửi nó không có gì, bạn sẽ nhận được một đầu ra None vì giá trị của yield sẽ là None.

yield from chính nó bằng None và bạn đang sử dụng hai trong số chúng. Tại số thứ hai yield from bạn đang lặp lại danh sách, đầu vào máy phát với các mục của danh sách đó, nhưng bạn cũng đang sử dụng yield from để trả về biểu thức trình tạo đó, trả về danh sách và chính nó tương đương với None tại mỗi lần lặp , vậy tại sao sau mỗi lần lặp lại phạm vi mục bạn nhận được None.

Về cơ bản đây là những gì đang xảy ra:

  1. (yield from y) for y in x mang lại các giá trị, [0, 1, 2]
  2. yield from mang lại các giá trị từ trước đó, và cũng yield from từ trước đó là None.
  3. Đánh giá [0, 1, 2] và sau đó thêm None do yield from trong (yield from y) for y in x.

Thật không may, không có cách nào để loại bỏ đầu ra None do tính chất của biểu thức. Bạn nên sử dụng from_iterable.

Nguồn giải thích biểu thức lợi nhuận; https://docs.python.org/2.5/ref/yieldexpr.html

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