जब आप अपने कोड को डीबग कर रहे हों या यदि कोई अपवाद फेंकता है, तो जेनरेटर आलसी-मूल्यांकन कर रहे हैं 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
आपके मामले में ऑपरेशन काफी सरल हैं और मुझे नहीं पता कि क्या इसके लिए कई फ़ंक्शन बनाने के लिए भी आवश्यक है, कोई आसानी से map
इसके बजाय अंतर्निहित या एक जनरेटर अभिव्यक्ति का उपयोग कर सकता है:
map(do_something, get_the_list()) # map
(do_something(i) for i in get_the_list()) # generator expression
उपयोग करने के लिए दोनों समान होना चाहिए (कुछ मतभेदों को छोड़कर)। और अगर उन्हें अधिक वर्णनात्मक नाम की आवश्यकता है, तो आप उन्हें अभी भी एक फ़ंक्शन में लपेट सकते हैं।
ऐसे कई हेल्पर्स हैं, जो बिल्ट-इन में मौजूद iterables पर बहुत ही सामान्य ऑपरेशन को लपेटते हैं और आगे के बिल्ट-इन itertools
मॉड्यूल में पाए जा सकते हैं । ऐसे सरल मामलों में मैं केवल इनका सहारा लेता हूं और केवल गैर-तुच्छ मामलों के लिए अपने स्वयं के जनरेटर लिखते हैं।
लेकिन मुझे लगता है कि आपका वास्तविक कोड अधिक जटिल है, जो लागू नहीं हो सकता है, लेकिन मैंने सोचा कि यह विकल्पों का उल्लेख किए बिना एक पूर्ण उत्तर नहीं होगा।