2008-12-13 18 views

उत्तर

94

आप सूची comprehensions समझ रहे हो? यदि ऐसा है, तो जनरेटर अभिव्यक्ति एक सूची समझ की तरह है, लेकिन उन सभी वस्तुओं को ढूंढने के बजाय जिन्हें आप रुचि रखते हैं और उन्हें सूची में पैक करते हैं, यह प्रतीक्षा करता है, और अभिव्यक्ति से प्रत्येक आइटम को एक-एक करके उत्पन्न करता है।

>>> my_list = [1, 3, 5, 9, 2, 6] 
>>> filtered_list = [item for item in my_list if item > 3] 
>>> print filtered_list 
[5, 9, 6] 
>>> len(filtered_list) 
3 
>>> # compare to generator expression 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> print filtered_gen # notice it's a generator object 
<generator object at 0xb7d5e02c> 
>>> len(filtered_gen) # So technically, it has no length 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: object of type 'generator' has no len() 
>>> # We extract each item out individually. We'll do it manually first. 
... 
>>> filtered_gen.next() 
5 
>>> filtered_gen.next() 
9 
>>> filtered_gen.next() 
6 
>>> filtered_gen.next() # Should be all out of items and give an error 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> # Yup, the generator is spent. No values for you! 
... 
>>> # Let's prove it gives the same results as our list comprehension 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> gen_to_list = list(filtered_gen) 
>>> print gen_to_list 
[5, 9, 6] 
>>> filtered_list == gen_to_list 
True 
>>> 

क्योंकि एक जनरेटर अभिव्यक्ति एक बार में केवल एक आइटम की उपज के लिए है, यह स्मृति के उपयोग में बड़ी बचत हो सकती है। जनरेटर अभिव्यक्ति परिदृश्यों में सबसे अधिक समझदारी बनाती है जहां आपको एक समय में एक आइटम लेने की आवश्यकता होती है, उस आइटम के आधार पर बहुत सी गणनाएं करें और फिर अगले आइटम पर जाएं। यदि आपको एक से अधिक मूल्य की आवश्यकता है, तो आप एक जनरेटर अभिव्यक्ति का भी उपयोग कर सकते हैं और एक समय में कुछ पकड़ सकते हैं। यदि आपको अपने कार्यक्रम की आय से पहले सभी मूल्यों की आवश्यकता है, तो इसके बजाय एक सूची समझ का उपयोग करें।

12

एक जनरेटर समझ एक सूची समझ के आलसी संस्करण है।

यह सिर्फ छोड़कर यह एक अगले() विधि है कि अगले तत्व निकलेगा के साथ एक वस्तु यानी सूची के बजाय एक iterator देता है कि एक सूची समझ की तरह है।

यदि आप सूची समझ से परिचित नहीं हैं तो here देखें और जनरेटर के लिए here देखें।

4

सूची/जनरेटर समझ एक निर्माण जो आपको एक मौजूदा एक से एक नई सूची/जनरेटर बनाने के लिए उपयोग कर सकते हैं।

मान लीजिए कि आप 10 1 से प्रत्येक संख्या के वर्गों की सूची आप अजगर में यह कर सकते हैं उत्पन्न करने के लिए चाहते हैं:

>>> [x**2 for x in range(1,11)] 
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 
यहाँ

, range(1,11) सूची [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] उत्पन्न करता है लेकिन range कार्य नहीं है पायथन 3.0 से पहले जनरेटर, और इसलिए मैंने जो निर्माण किया है वह एक सूची समझ है।

अगर मैं एक जनरेटर वही चीज़ बनाना चाहता था, मैं इसे इस तरह कर सकता है:

>>> (x**2 for x in xrange(1,11)) 
<generator object at 0x7f0a79273488> 

अजगर 3 में, हालांकि, range एक जनरेटर है, इसलिए परिणाम वाक्य रचना पर ही निर्भर करता है आप (स्क्वायर ब्रैकेट या राउंड ब्रैकेट्स) का उपयोग करते हैं।

+1

यह गलत है। बाहरी अभिव्यक्ति एक जनरेटर के साथ आंतरिक अभिव्यक्ति है या नहीं, इसके साथ कुछ भी नहीं है। हालांकि जाहिर है, आमतौर पर एक सूची से तत्व लेने वाले जनरेटर अभिव्यक्ति में अधिक बिंदु नहीं है, आप इसे कर सकते हैं। – Antimony

+0

क्या इसे और अधिक स्पष्ट रूप से लिखा जा सकता है? मैं जो कह रहा हूं उसे प्राप्त करता हूं, लेकिन एंटीमोनी कहता है, ऐसा लगता है कि आप कुछ और कह रहे हैं। (और ऐसा लगता है कि आप कह रहे हैं कि गलत है) –

2

जेनरेटर समझ एक निश्चित संरचना के साथ जनरेटर बनाने का एक आसान तरीका है। मान लें कि आप generator चाहते हैं जो your_list में सभी को एक-एक करके आउटपुट करता है। आप समारोह शैली का उपयोग करके इसे बनाते हैं तो वह ऐसा होगा:

def allEvens(L): 
    for number in L: 
     if number % 2 is 0: 
      yield number 

evens = allEvens(yourList) 

आप इस जनरेटर समझ अभिव्यक्ति के साथ एक ही परिणाम प्राप्त कर सकते थे:

evens = (number for number in your_list if number % 2 == 0) 

दोनों ही मामलों में, जब आप next(evens) आप कॉल your_list में अगला नंबर भी प्राप्त करें।

0

जेनरेटर समझ, iterables बनाने के लिए एक कर्सर जो एक संसाधन पर ले जाता है की तरह कुछ एक दृष्टिकोण है। यदि आप mysql कर्सर या mongodb कर्सर को जानते हैं, तो आप इस बात से अवगत हो सकते हैं कि पूरे वास्तविक डेटा को स्मृति में कभी भी लोड नहीं किया जाता है, लेकिन एक समय में। आपका कर्सर आगे और पीछे चलता है, लेकिन स्मृति में हमेशा एक पंक्ति/सूची तत्व होता है।

संक्षेप में, जेनरेटर समझ का उपयोग करके आप पाइथन में आसानी से कर्सर बना सकते हैं।

0

जेनरेटर समझ का एक और उदाहरण:

print 'Generator comprehensions' 

def sq_num(n): 
    for num in (x**2 for x in range(n)):  
     yield num 

for x in sq_num(10): 
    print x 
संबंधित मुद्दे