2013-01-29 7 views
6

Nach this, Die maximale Größe einer Python-Liste auf einem 32-Bit-System beträgt 536.870.912 Elemente.Erstellen einer Liste, die die maximale Größe in Python überschreitet

Gibt es eine Möglichkeit, eine Liste mit einer größeren Größe zu initialisieren?

Sagen sie:

list1 = [None]*1000000000 
+3

Nun, nein, das ist, was eine "maximale Größe" bedeutet. Sie können 'itertools.chain' ein Bündel von Stücken zusammen, denke ich, wenn Sie die Erinnerung haben. –

+3

Haben Sie berücksichtigt, dass jedes Element einer Liste mindestens 4 Bytes belegt, also '4 * 536, 870, 912 = 2147483648'. Nun, das sind 2 GB RAM nur für die Liste. Wenn die Elemente nicht identisch sind, bin ich ziemlich sicher, dass Sie einen MemoryError-Weg bekommen werden, bevor Sie diese Größe erreichen. – Bakuriu

+1

@bakuriu danke für das darauf hin. Ich habe einen MemoryError bekommen. :( –

Antwort

10

Listen, dass große eine große Menge an Platz in Anspruch nehmen würde, da jedes Element in der Liste mindestens 4 Bytes besetzen würde, also nur eine Liste mit maximal erlaubten Elementen einnehmen würde mindestens 2 GB RAM . Und das ist ohne Berücksichtigung 64-Bit-Systeme .

  1. 4 * 5.4e+8 = 2.1e+9, 2,1 GB
  2. 8 * 1.2e+18 = 9.2+18, 9.2 EB (ja, Exabyte)

aus Gründen der Frage jedoch, nehmen wir an, dass Sie eine Menge RAM.


Eine der einfachsten Optionen wäre, ein eigenes Objekt zu erstellen, das die umfangreiche Liste enthält. Es würde im Grunde die riesige Liste in kleinere Listen aufteilen und dann bei Bedarf entsprechend darauf zugreifen. Da es no real benefits of subclassing list gibt, weil Sie sowieso alle Methoden neu schreiben müssten, wäre es besser, nur object zu unterklassifizieren und dann von dort zu gehen. Das einzige, was hier wichtig ist, ist, niemals die Unterlisten zu kombinieren oder zu kopieren (weil sie massiv sind), also verwenden Sie itertools.chain, um die Listen bei Bedarf zu überfliegen. Hier

ist ein Beispiel für die einfachstenen Listen Methoden append, extend, get/setitem Arbeits:

import sys 
from itertools import chain 

class largeList(object): 
    def __init__(self, mylist=[]): 
     self.maxSize = sys.maxsize/4 
     self.src = [[]] 
     self.extend(mylist) 

    def __iter__(self): 
     return chain(*self.src) 

    def __getitem__(self, idx): 
     return self.src[int(idx/self.maxSize)][idx%self.maxSize] 

    def __setitem__(self, idx, item): 
     self.src[int(idx/self.maxSize)][idx%self.maxSize] = item 
     # expand set/getitem to support negative indexing. 

    def append(self, item): 
     if len(self.src[-1]) < self.maxSize: 
      self.src[-1].append(item) 
     else: 
      self.src.append([item]) 

    def extend(self, items): 
     remainder = self.maxSize - len(self.src[-1]) 
     self.src[-1].extend(items[:remainder]) 
     for i in xrange(0, len(items[remainder:]), self.maxSize): 
      self.src.append(items[remainder:][i:i+self.maxSize]) 

    def __len__(self): 
     return sum(len(l) for l in self.src) 

    def __str__(self): 
     size = self.__len__() 
     if size >= 8: 
      first, last = [], [] 
      for i, ele in enumerate(self.__iter__()): 
       if i < 3: 
        first.append(ele) 
       if i >= size - 3: 
        last.append(ele) 
      return str(first)[:-1] + ', ..., ' + str(last)[1:] 
     return str(list(self.__iter__())) 

Beispiel für die Verwendung (, wenn Sie weniger als 4 GB freier RAM oder Sie sind auf einem 64-Bit-System ändern, sys.maxsize vor diesem Versuch):

#sys.maxsize = 1000 

list1 = largeList(xrange(sys.maxsize/4 + 2)) 
print len(list1) 
# 53687093 
print list1 
#[0, 1, 2, ..., 536870910, 536870911, 536870912] 
print list1.src 
#[[0, 1, 2 ..., 536870910], [536870911, 536870912]] 
list1.extend([42, 43]) 
print list1 
#[0, 1, 2, ..., 536870912, 42, 43] 

das Ergebnis: intern die Listen in mehrere Listen aufgeteilt werden, während sie erscheinen ju zu sein das erste bei der Arbeit mit ihnen. Weitere list Funktionalitäten können einfach durch Hinzufügen weiterer Methoden hinzugefügt werden. Z.B. pop, remove, insert und index:

(...) 

    def pop(self, idx): 
     listidx = int(idx/self.maxSize) 
     itempopped = self.src[listidx].pop(idx%self.maxSize) 
     for i in xrange(listidx, len(self.src)-1): 
      self.src[i].append(self.src[i+1].pop(0)) 
     if not self.src[-1]: 
      del self.src[-1] 
     return itempopped 

    def remove(self, item): 
     for i, ele in enumerate(self.__iter__()): 
      if ele == item: 
       self.pop(i) 
       break 

    def insert(self, idx, item): 
     listidx = int(idx/self.maxSize) 
     itemtoshift = self.src[listidx].pop(-1) 
     self.src[listidx].insert(idx%self.maxSize, item) 
     for i in xrange(listidx+1, len(self.src)-1): 
      itemremoved = self.src[i].pop(-1) 
      self.src[i].insert(0, itemtoshift) 
      itemtoshift = itemremoved 
     if len(self.src[-1]) < self.maxSize: 
      self.src[-1].insert(0, itemtoshift) 
     else: 
      self.src.append([self.src[-1].pop(-1)]) 
      self.src[-2].insert(0, itemtoshift) 

    def index(self, item): 
     for i, ele in enumerate(self.__iter__()): 
      if ele == item: 
       return i 
     return -1 

Beispiel für die Verwendung, Fortsetzung:

#sys.maxsize = 1000 

list1 = largeList(xrange(sys.maxsize/4 + 2)) 
list1.insert(0, 'a') 
print list1 
#['a', 0, 1, ..., 536870910, 536870911, 536870912] 
list1.pop(2) 
#1 
list1.remove(536870910) 
print list1.index('a') 
#0 
print len(list1) 
#536870911 
print list1 
#['a', 0, 2, ..., 536870909, 536870911, 536870912] 
print list.src 
#[['a', 0, 2, ..., 536870909, 536870911], [536870912]] 
Verwandte Themen