3 回答

TA貢獻1843條經驗 獲得超7個贊
如果您不使用收益率*,則可以隨時將其轉換為:
yield from foo
…變成這樣:
for bar in foo:
yield bar
可能會有性能成本**,但從語義上講永遠不會有差異。
是否將兩個半部分(上半部分和下半部分)中的條目彼此追加到一個列表中,以使父遞歸函數與call的收益并同時使用這兩個半部分?
沒有!迭代器和生成器的全部要點是,您無需構建實際的列表并將它們附加在一起。
但是效果是相似的:您只是從一種收益,然后從另一種收益。
如果您將上半部分和下半部分視為“懶惰列表”,則可以,您可以將其視為“懶惰附加”,它會創建一個較大的“懶惰列表”。而且,如果您調用list父函數的結果,那么您當然會得到一個實際值list,該值等于將如果執行yield list(…)而不是所獲得的兩個列表加在一起yield from …。
但是我認為反過來更容易想到:它的作用與for循環完全相同。
如果將兩個迭代器保存到變量中并進行循環itertools.chain(upper, lower),則與在第一個循環然后在第二個循環上進行相同,對嗎?沒什么區別。實際上,您可以實現chain如下:
for arg in *args:
yield from arg
*不是生成器產生給調用者的值,而是生成器內部的yield表達式本身的值(使用send方法從調用者產生),如PEP 342中所述。您沒有在示例中使用這些。而且我敢打賭您不在您的真實代碼中。但是協程式代碼通常使用yield from表達式的值- 有關示例,請參閱PEP 3156。此類代碼通常取決于Python 3.3生成器的其他功能-特別是StopIteration.value來自引入了同一PEP 380的新功能yield from-因此必須將其重寫。但是,如果沒有,您可以使用PEP來向您顯示完整的,混亂的等價物,當然您也可以減少不需要的部分。而且,如果您不使用表達式的值,它將縮減為上面的兩行。
**數量不多,除了使用Python 3.3或完全重組代碼外,您無能為力。這與將列表解析轉換為Python 1.5循環完全相同,或者在XY版本中進行了新的優化并且您需要使用舊版本時,則與其他情況完全相同。

TA貢獻1775條經驗 獲得超11個贊
我只是碰到這個問題,我使用的是一個有點困難,因為我需要返回值的yield from:
result = yield from other_gen()
不能將其表示為簡單的for循環,但可以用以下方式重現:
_iter = iter(other_gen())
try:
while True: #broken by StopIteration
yield next(_iter)
except StopIteration as e:
if e.args:
result = e.args[0]
else:
result = None
希望這將幫助遇到相同問題的人們。:)

TA貢獻1794條經驗 獲得超8個贊
用for循環替換它們:
yield from range(L[start] + 1, L[end])
==>
for i in range(L[start] + 1, L[end]):
yield i
關于元素也是如此:
yield from missing_elements(L, index, end)
==>
for el in missing_elements(L, index, end):
添加回答
舉報