2013-05-19 15 views
7

पायथन के itertools.cycle के लिए दस्तावेज़() के रूप में एक छद्म कोड कार्यान्वयन देता है:पायथन की itertools.cycle को पुनरावर्तनीय की एक प्रति बनाने की आवश्यकता क्यों है?

def cycle(iterable): 
    # cycle('ABCD') --> A B C D A B C D A B C D ... 
    saved = [] 
    for element in iterable: 
     yield element 
     saved.append(element) 
    while saved: 
     for element in saved: 
       yield element 

नीचे, यह कहा गया है: "ध्यान दें, टूलकिट का यह सदस्य महत्वपूर्ण सहायक भंडारण की आवश्यकता हो सकती (की लंबाई के आधार पुनरावृत्त)। "

मैं मूल रूप से इस मार्ग नीचे जा रहा था, को छोड़कर मैं ऐसा किया, जो iterable की एक प्रति बनाने की आवश्यकता नहीं है:

def loop(iterable): 
    it = iterable.__iter__() 

    while True: 
     try: 
      yield it.next() 
     except StopIteration: 
      it = iterable.__iter__() 
      yield it.next() 

x = {1, 2, 3} 

hard_limit = 6 
for i in loop(x): 
    if hard_limit <= 0: 
     break 

    print i 
    hard_limit -= 1 

प्रिंट:

1 
2 
3 
1 
2 
3 

हाँ, मैं अपने कार्यान्वयन का एहसास str के लिए काम नहीं करेगा, लेकिन यह किया जा सकता है। मैं और अधिक उत्सुक हूं कि यह एक और प्रति क्यों बनाता है। मुझे लगता है कि इसे कचरा संग्रह के साथ करना है, लेकिन मुझे पाइथन के इस क्षेत्र में अच्छी तरह से अध्ययन नहीं किया जाता है।

धन्यवाद!

+0

@Martijn आपने सिंटैक्स हाइलाइटिंग को कैसे जोड़ा? मैं यह नहीं समझ सका कि यह कैसे करें ... – stantonk

+0

मैंने नहीं किया; मैंने 'पायथन' टैग जोड़ा और फिर हाइलाइटिंग स्वचालित रूप से लागू होती है। लेकिन टैग हाइलाइटिंग के बिना भी अक्सर वैसे भी सटीक अनुमान लगाया जाता है। –

+0

अहह, लेकिन पायथन 2.7 टैग नहीं है? अजीब ... – stantonk

उत्तर

11

Iterables केवल पर पर फिर से चालू किया जा सकता है।

आप इसके बजाय अपने लूप में नया बनाते हैं। चक्र ऐसा नहीं कर सकता है, इसे जो कुछ भी आपने पारित किया है उसके साथ काम करना है। cycle बस इसे पुन: सक्रिय नहीं कर सकता है। इस प्रकार मूल पुनरावर्तक के सभी तत्वों को स्टोर करने के लिए मजबूर किया जाता है।

आप के बजाय निम्नलिखित जनरेटर में पारित करने के लिए थे, तो आपका loop() विफल रहता है:

def finite_generator(source=[3, 2, 1]): 
    while source: 
     yield source.pop() 

अब आप अपने loop() पैदा करता है:

>>> hard_limit = 6 
>>> for i in loop(finite_generator()): 
...  if hard_limit <= 0: 
...   break 
...  print i 
...  hard_limit -= 1 
... 
1 
2 
3 

आपका कोड केवल जिसके लिए cycle() का उपयोग कर, दृश्यों के लिए काम करेगा अधिक होगा; उस मामले में आपको cycle() के स्टोरेज बोझ की आवश्यकता नहीं है। इसे नीचे सरल करें:

def loop_sequence(seq): 
    while True: 
     for elem in seq: 
      yield elem 
+0

मुझे सच में यकीन नहीं है कि आपका जवाब क्या है ... मेरा सवाल यह है कि इनपुट की एक प्रति बनाने की आवश्यकता क्यों है? वे सहायक भंडारण प्रभावों को ध्यान में रखते हुए एक बिंदु बनाते हैं ... क्यों न केवल उस समस्या को हल करें? – stantonk

+0

@stantonk: यही वह है जिसे मैं संबोधित कर रहा हूं; मैं आपको दिखा रहा हूं कि कैसे इटरेटर केवल अपने तत्व * एक बार * उत्पन्न कर सकते हैं। यदि आप उन्हें दोहराना जारी रखना चाहते हैं तो आपको उन तत्वों को स्टोर करने की आवश्यकता है। –

+0

@stantonk: आप नए इटरेटर बनाने की 'सेट की क्षमता से धोखा दे रहे थे; इसमें तत्व अभी भी हैं इसलिए हर बार एक ही तत्व के लिए एक नया इटरेटर उत्पन्न कर सकते हैं। –

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