2010-03-29 8 views
5

मैंने जेनरेटर सुविधा का अध्ययन किया है और मुझे लगता है कि मुझे यह मिला है, लेकिन मैं समझना चाहता हूं कि मैं इसे अपने कोड में कहां लागू कर सकता हूं।आप अपने पायथन कोड में जेनरेटर सुविधा का उपयोग कहां करते हैं?

मेरे मन में निम्न उदाहरण मैं "अजगर आवश्यक संदर्भ" पुस्तक में पढ़ा है:

# tail -f 
def tail(f): 
    f.seek(0,2) 
    while True: 
    line = f.readline() 
    if not line: 
    time.sleep(0.1) 
    continue 
    yield line 

आप किसी भी अन्य प्रभावी उदाहरण है, जहां जनरेटर पूंछ -f की तरह इस काम के लिए सबसे अच्छा उपकरण हैं है?

आप जेनरेटर सुविधा का कितनी बार उपयोग करते हैं और किस प्रकार की कार्यक्षमता \ प्रोग्राम का आप आमतौर पर इसे लागू करते हैं?

+1

कृपया इसे एक सामुदायिक विकी प्रश्न बनाएं। –

उत्तर

6

जब मैं स्कैनर (टोकननाइज़र) लागू करता हूं या जब मैं डेटा कंटेनरों पर पुन: प्रयास करता हूं तो मैं उन्हें बहुत उपयोग करता हूं।

संपादित करें:

whitespace = ' \t\r\n' 
operators = '~!%^&*()-+=[]{};:\'"/?.,<>\\|' 

def scan(s): 
    "returns a token and a state/token id" 
    words = {0:'', 1:'', 2:''} # normal, operator, whitespace 
    state = 2 # I pick ws as first state 
    for c in s: 
     if c in operators: 
      if state != 1: 
       yield (words[state], state) 
       words[state] = '' 
      state = 1 
      words[state] += c 
     elif c in whitespace: 
      if state != 2: 
       yield (words[state], state) 
       words[state] = '' 
      state = 2 
      words[state] += c 
     else: 
      if state != 0: 
       yield (words[state], state) 
       words[state] = '' 
      state = 0 
      words[state] += c 
    yield (words[state], state) 

प्रयोग उदाहरण: यहाँ एक डेमो tokenizer मैं एक सी ++ वाक्य रचना उजागर कार्यक्रम के लिए इस्तेमाल किया है,

>>> it = scan('foo(); i++') 
>>> it.next() 
('', 2) 
>>> it.next() 
('foo', 0) 
>>> it.next() 
('();', 1) 
>>> it.next() 
(' ', 2) 
>>> it.next() 
('i', 0) 
>>> it.next() 
('++', 1) 
>>> 
+0

क्या आप टोकननाइज़र के कुछ सरल स्निपेट पोस्ट कर सकते हैं? – systempuntoout

+0

@systempuntoout, ठीक है, मैंने एक नमूना पोस्ट किया। –

+0

अच्छा उदाहरण, बहुत धन्यवाद! – systempuntoout

4

जब भी अपने कोड या तो मूल्यों के असीमित संख्या उत्पन्न होगा या अधिक आम तौर पर अगर बहुत अधिक स्मृति पहली बार में पूरी सूची उत्पन्न करके भस्म हो जाएगा।

या अगर यह है कि आप पूरे उत्पन्न सूची पर पुनरावृति नहीं कर की संभावना है (और सूची बहुत बड़ी है)। मेरा मतलब है कि अगर इसका उपयोग नहीं किया जाता है तो पहले हर मूल्य (और पीढ़ी के लिए इंतजार) उत्पन्न करने में कोई बात नहीं है।

जेनरेटर के साथ मेरा नवीनतम मुठभेड़ तब था जब मैंने एक रैखिक आवर्ती अनुक्रम (एलआरएस) जैसे लागू किया। फाइबोनैकी अनुक्रम।

+1

-1: सामान्य रूप से इटरेटर के विवरण की तरह मुझे लगता है, जेनरेटर फ़ंक्शंस नहीं, इसलिए यह बिंदु को याद करता है। इस जवाब को कोई उपरांत क्यों मिला? – nikow

+0

@nikow: हाँ यह अधिक सामान्य है, लेकिन मैं यह नहीं कहूंगा कि यह इटरेटर के * विवरण * है। यह एक अमूर्त विवरण है जिसमें परिस्थितियों जेनरेटर उपयोगी हो सकते हैं। जनरेटर कुछ प्रकार के इटरेटर हैं .. :) –

1

सामान्य तौर पर अलग डेटा प्राप्ति के लिए (जटिल हो सकता है) खपत से विशेष रूप से:

  • कई बी-वृक्ष प्रश्नों के परिणामों को श्रेणीबद्ध करने के लिए - db हिस्सा उत्पन्न करता है और प्रश्नों निष्पादित करता yield हर एक से रिकॉर्ड आईएनजी, उपभोक्ता केवल पहुंचने एकल डेटा आइटम को देखता है।
  • बफरिंग (पढ़ना-आगे) - जनरेटर ब्लॉक में डेटा लाता है और प्रत्येक ब्लॉक से एकल तत्व उत्पन्न करता है। फिर, उपभोक्ता को गोरी के विवरण से अलग किया गया है।

जनरेटर कोरआउट के रूप में भी काम कर सकते हैं। आप डेटा में 0 उपभोक्ता पक्ष पर nextval=g.next(data) और data = yield(nextval) जनरेटर पक्ष पर उपयोग कर सकते हैं। इस मामले में जनरेटर और उसके उपभोक्ता 'स्वैप' मान। आप जेनरेटर संदर्भ में yield अपवाद फेंक सकते हैं: g.throw(exc) ऐसा करता है।

+0

बफरिंग एक महान उदाहरण है, धन्यवाद। – systempuntoout

2

उन सभी मामलों में जहां मेरे पास कुछ भी पढ़ने वाले एल्गोरिदम हैं, मैं विशेष रूप से जेनरेटर का उपयोग करता हूं।

क्यों?

एकाधिक जेनरेटर के संदर्भ में फ़िल्टरिंग, मैपिंग और कमी नियमों में लेयरिंग इतना आसान है।

उदाहरण:

def discard_blank(source): 
    for line in source: 
     if len(line) == 0: 
      continue 
     yield line 

def clean_end(source): 
    for line in source: 
     yield line.rstrip() 

def split_fields(source): 
    for line in source; 
     yield line.split() 

def convert_pos(tuple_source, position): 
    for line in tuple_source: 
     yield line[:position]+int(line[position])+line[position+1:] 

with open('somefile','r') as source: 
    data= convert_pos(split_fields(discard_blank(clean_end(source))), 0) 
    total= 0 
    for l in data: 
     print l 
     total += l[0] 
    print total 

मेरी प्राथमिकता कई छोटे जनरेटर का उपयोग करने के लिए इतना है कि एक छोटा सा परिवर्तन पूरी प्रक्रिया श्रृंखला के लिए विघटनकारी नहीं है।

+0

काम भी ठीक से काम नहीं करेगा? –

+2

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

+0

@ जे। टी। हर्ले: मुझे नहीं पता कि "बस के रूप में" क्या मतलब है, लेकिन जनरेटर मध्यवर्ती परिणाम नहीं बनाते हैं, जहां आम तौर पर कार्य करते हैं। नेस्टेड जनरेटर एक प्रकार का नक्शा-पाइपलाइन को कम करते हैं। –

संबंधित मुद्दे