2012-06-29 11 views
6

फैलती है मैं पॉप -11 से pdtolist के पाइथन समकक्ष कैसे बना सकता हूं?गतिशील सूची जो स्वचालित रूप से

मान लें कि मेरे पास जी नामक जनरेटर है जो एक समय में एक पूर्णांक (कहता है) पूर्ण करता है। मैं एक सूची एक बनाना चाहता हूं जो स्वचालित रूप से बढ़ता है क्योंकि मैं सूची के वर्तमान छोर से परे मूल्यों के लिए पूछता हूं। उदाहरण के लिए:

print a # => [ 0, 1, 2, g] 
print a[0] # => 0 
print a[1] # => 1 
print a[2] # => 2 
# (obvious enough up to here) 

print a[6] # => 6 
print a # => [ 0, 1, 2, 3, 4, 5, 6, g] 
# list has automatically expanded 

a = a[4:] # discard some previous values 
print a # => [ 4, 5, 6, g] 
print a[0] # => 4 

शब्दावली - एक संभावना गलतफहमी का अनुमान लगाने की: एक सूची एक "गतिशील सरणी" है, लेकिन है कि मैं क्या मतलब नहीं है; मुझे एक और अधिक अमूर्त भावना में "गतिशील सूची" चाहिए।

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

+0

'इंडेक्स एरर' को पकड़ने के लिए सूची की '__getitem__' विधि को ओवरराइड करें। –

+0

तो आपके पास सूची 'एल' है और' एल [99 99 99 999] 'प्रदर्शन करती है - सूची उस लंबाई बननी चाहिए? –

+0

हां, सिद्धांत रूप में। चेतावनी प्रोग्रामर! –

उत्तर

2

विचारों का योगदान करने वाले सभी लोगों के लिए बहुत धन्यवाद! यहां सभी प्रतिक्रियाओं से मैंने एकत्र किया है। यह सामान्य सूची वर्ग से अधिक कार्यक्षमता बरकरार रखता है, अतिरिक्त आवश्यकताओं को पूरा करने के लिए आवश्यक अतिरिक्त व्यवहार जोड़ता है।

class DynamicList(list): 
    def __init__(self, gen): 
     self.gen = gen 

    def __getitem__(self, index): 
     while index >= len(self): 
      self.append(next(self.gen)) 
     return super(DynamicList, self).__getitem__(index) 

    def __getslice__(self, start, stop): 
     # treat request for "last" item as "most recently fetched" 
     if stop == 2147483647: stop = len(self) 
     while stop > len(self): 
      self.append(next(self.gen)) 
     return super(DynamicList, self).__getslice__(start, stop) 

    def __iter__(self): 
     return self 

    def next(self): 
     n = next(self.gen) 
     self.append(n) 
     return n 

a = DynamicList(iter(xrange(10))) 

पहले जेनरेट किए गए मानों को आइटम या स्लाइस के रूप में व्यक्तिगत रूप से एक्सेस किया जा सकता है। दर्ज किए गए इतिहास को आवश्यकतानुसार विस्तारित किया जाता है यदि अनुरोधित आइटम सूची के वर्तमान छोर से बाहर हैं। पूरे रिकॉर्ड किए गए इतिहास को print a का उपयोग करके, या b = a[:] का उपयोग करके सामान्य सूची में असाइन किया जा सकता है। रिकॉर्ड किए गए इतिहास का एक टुकड़ा del a[0:4] का उपयोग करके हटाया जा सकता है। आप for का उपयोग करके पूरी सूची में फिर से शुरू कर सकते हैं, जैसे ही आप जाते हैं, या जब भी यह सूट हो जाता है। क्या आप जेनरेट किए गए मानों के अंत तक पहुंच सकते हैं, StopIteration उठाया गया है।

कुछ अजीबता बनी हुई है। a = a[0:4] जैसे असाइनमेंट सफलतापूर्वक इतिहास को छोटा कर देते हैं, लेकिन परिणामी सूची अब ऑटो-विस्तार नहीं करती है। स्वचालित विकास गुणों को बनाए रखने के लिए del a[0:4] का उपयोग करें। इसके अलावा, मैं एक जादू मूल्य, 2147483647 पहचानने के साथ पूरी तरह से खुश नहीं हूं, जो सबसे हालिया आइटम का प्रतिनिधित्व करता है।

2

यह हो सकती है कि आप आरंभ:

class DynamicList(list): 
    def __init__(self, gen): 
     self._gen = gen 

    def __getitem__(self, index): 
     while index >= len(self): 
      self.append(next(self._gen)) 
     return super(DynamicList, self).__getitem__(index) 

आप स्लाइस (वर्तमान में, वे सिर्फ एक सामान्य सूची लौटने के लिए, ताकि आप गतिशील व्यवहार खोना) के लिए कुछ विशेष हैंडलिंग जोड़ने की आवश्यकता होगी। साथ ही, यदि आप जेनरेटर को एक सूची आइटम बनना चाहते हैं, तो इसमें कुछ जटिलता शामिल होगी।

+0

यह एक सूची सबक्लास नहीं होना चाहिए; '__init__' असंगत है और इसे' __len__' या '__setitem__' का समर्थन नहीं करना चाहिए ... – agf

+0

@agf:' __init__' समस्या एक मान्य बिंदु है, लेकिन इसे '__len__' या' __setitem__' का समर्थन क्यों नहीं करना चाहिए? – voithos

+0

इसकी लंबाई अज्ञात है क्योंकि जेनरेटर की लंबाई अज्ञात है, और इसे केवल जनरेटर से आइटम प्रतिबिंबित करना चाहिए, इसलिए आपको इसे असाइन करने में सक्षम नहीं होना चाहिए। – agf

1

बस एक और इसी तरह के प्रश्न का उत्तर दिया और आपके जवाब को अपडेट करने का निर्णय लिया यह कैसे है?

class dynamic_list(list): 
    def __init__(self,num_gen): 
     self._num_gen = num_gen 
    def __getitem__(self,index): 
     if isinstance(index, int): 
      self.expandfor(index) 
      return super(dynamic_list,self).__getitem__(index) 

     elif isinstance(index, slice): 
      if index.stop<index.start: 
       return super(dynamic_list,self).__getitem__(index) 
      else: 
       self.expandfor(index.stop if abs(index.stop)>abs(index.start) else index.start) 
      return super(dynamic_list,self).__getitem__(index) 

    def __setitem__(self,index,value): 
     if isinstance(index, int): 
      self.expandfor(index) 
      return super(dynamic_list,self).__setitem__(index,value) 

     elif isinstance(index, slice): 
      if index.stop<index.start: 
       return super(dynamic_list,self).__setitem__(index,value) 
      else: 
       self.expandfor(index.stop if abs(index.stop)>abs(index.start) else index.start) 
      return super(dynamic_list,self).__setitem__(index,value) 

    def expandfor(self,index): 
      rng = [] 
      if abs(index)>len(self)-1: 
       if index<0: 
        rng = xrange(abs(index)-len(self)) 
       else: 
        rng = xrange(abs(index)-len(self)+1) 
      for i in rng: 
       self.append(self._num_gen.next()) 
संबंधित मुद्दे