เครื่องกำเนิดไฟฟ้าจะทำการประเมินแบบขี้เกียจดังนั้นreturn
หรือyield
จะทำงานแตกต่างกันเมื่อคุณทำการดีบั๊กโค้ดของคุณหรือถ้ามีข้อผิดพลาดเกิดขึ้น
ด้วยreturn
ข้อยกเว้นใด ๆ ที่เกิดขึ้นกับคุณคุณgenerator
จะไม่รู้อะไรเลยgenerate_all
นั่นเป็นเพราะเมื่อgenerator
มีการดำเนินการจริง ๆ คุณได้ออกจากgenerate_all
ฟังก์ชันไปแล้ว ด้วยyield
ในนั้นมันจะมีgenerate_all
ในการย้อนกลับ
def generator(some_list):
for i in some_list:
raise Exception('exception happened :-)')
yield i
def generate_all():
some_list = [1,2,3]
return generator(some_list)
for item in generate_all():
...
Exception Traceback (most recent call last)
<ipython-input-3-b19085eab3e1> in <module>
8 return generator(some_list)
9
---> 10 for item in generate_all():
11 ...
<ipython-input-3-b19085eab3e1> in generator(some_list)
1 def generator(some_list):
2 for i in some_list:
----> 3 raise Exception('exception happened :-)')
4 yield i
5
Exception: exception happened :-)
และถ้ามันใช้yield from
:
def generate_all():
some_list = [1,2,3]
yield from generator(some_list)
for item in generate_all():
...
Exception Traceback (most recent call last)
<ipython-input-4-be322887df35> in <module>
8 yield from generator(some_list)
9
---> 10 for item in generate_all():
11 ...
<ipython-input-4-be322887df35> in generate_all()
6 def generate_all():
7 some_list = [1,2,3]
----> 8 yield from generator(some_list)
9
10 for item in generate_all():
<ipython-input-4-be322887df35> in generator(some_list)
1 def generator(some_list):
2 for i in some_list:
----> 3 raise Exception('exception happened :-)')
4 yield i
5
Exception: exception happened :-)
อย่างไรก็ตามสิ่งนี้มาพร้อมกับราคา เลเยอร์ตัวสร้างเพิ่มเติมมีค่าใช้จ่ายบางส่วน ดังนั้นreturn
โดยทั่วไปจะเร็วกว่าyield from ...
(หรือfor item in ...: yield item
) เล็กน้อย ในกรณีส่วนใหญ่สิ่งนี้จะไม่สำคัญมากนักเพราะสิ่งที่คุณทำในเครื่องกำเนิดไฟฟ้ามักจะควบคุมเวลาทำงานเพื่อให้เลเยอร์เพิ่มเติมไม่สามารถสังเกตเห็นได้
อย่างไรก็ตามyield
มีข้อได้เปรียบเพิ่มเติมบางประการ: คุณไม่ได้ จำกัด การทำซ้ำได้เพียงครั้งเดียวคุณยังสามารถเพิ่มรายการเพิ่มเติมได้อย่างง่ายดาย:
def generator(some_list):
for i in some_list:
yield i
def generate_all():
some_list = [1,2,3]
yield 'start'
yield from generator(some_list)
yield 'end'
for item in generate_all():
print(item)
start
1
2
3
end
ในกรณีของคุณการดำเนินการค่อนข้างง่ายและฉันไม่ทราบว่าจำเป็นต้องสร้างฟังก์ชั่นหลายอย่างสำหรับสิ่งนี้หรือไม่เราสามารถใช้ built-in map
หรือ expression ของเครื่องแทนได้อย่างง่ายดาย:
map(do_something, get_the_list()) # map
(do_something(i) for i in get_the_list()) # generator expression
ทั้งสองควรเหมือนกัน (ยกเว้นความแตกต่างบางอย่างเมื่อใช้ข้อยกเว้น) และหากพวกเขาต้องการชื่อที่มีความหมายมากกว่านี้คุณก็สามารถสรุปได้ในฟังก์ชันเดียว
มีผู้ช่วยหลายคนที่รวมการดำเนินการทั่วไปไว้ใน iterables ในตัวและสามารถพบได้ในitertools
โมดูลในตัว ในกรณีที่เรียบง่ายเช่นนี้ฉันจะหันไปใช้สิ่งเหล่านี้และเฉพาะกรณีที่ไม่สำคัญเขียนเครื่องปั่นไฟของคุณเอง
แต่ฉันคิดว่ารหัสจริงของคุณมีความซับซ้อนมากขึ้นเพื่อที่จะไม่สามารถใช้งานได้ แต่ฉันคิดว่ามันจะไม่เป็นคำตอบที่สมบูรณ์โดยไม่ต้องพูดถึงทางเลือกอื่น