2013-01-29 3 views
6

thisによると、32ビットシステムでのPythonリストの最大サイズは536,870,912要素です。Pythonで最大サイズを超えるリストを作成する方法

リストよりも大きなサイズのリストを初期化する方法はありますか?

さんが言ってみましょう:リストの各要素はとても許容される最大の要素を持つ一つだけのリストを取るだろう、少なくとも4つのバイトを占めるように大きなは、宇宙の大規模な量を取るだろうと

list1 = [None]*1000000000 
+3

まあ、いや、それは "最大サイズ" は何を意味するかです。あなたがメモリを持っているならば、あなたは 'itertools.chain'一緒にたくさんのチャンクを作ることができます。 –

+3

リストの各要素は、少なくとも4バイトを占めていることを考慮しました。したがって、 '4 * 536,870,912 = 2147483648'です。今はリストのためだけに2GBのRAMです。要素が同一でない場合、私はあなたがそのサイズに達する前にMemoryErrorの方法を得るだろうと確信しています。 – Bakuriu

+1

@bakuriuそれを指摘してくれてありがとう。私はMemoryErrorを取得しました。 :( –

答えて

10

リスト最小2GBのRAM 。そして、それは64ビットシステムを考慮しなくてもです。

  1. 4 * 5.4e+8 = 2.1e+9、2.1ギガバイト
  2. 8 * 1.2e+18 = 9.2+18、9.2 EB(はい、エクサバイト)

しかし、質問のために、あなたは多くのRAMを持っていると仮定しましょう。


最も簡単なオプションの1つは、大量のリストを保持して処理する独自のオブジェクトを作成することです。基本的には大量のリストを小さなリストに分割し、必要に応じてそれにアクセスします。とにかくすべてのメソッドを書き直さなければならないので、no real benefits of subclassing listがあるので、objectをサブクラス化してからそこに行く方がよいでしょう。ここで重要なのは、サブリストが大量であるため、結合またはコピーしないことです。したがって、必要に応じてリストをループするにはitertools.chainを使用してください。ここで

、最も単純なリスト-方法の一例appendあるextendget/setitem作業:あなたは4ギガバイトの無料RAM未満を持っているか、あなたは、64ビットシステム上にある場合

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__())) 

例(を使用、これをしようとする前sys.maxsizeを変更):!

#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] 

結果:彼らは柱のように見える一方で、内部リストは、複数のリストに分割されていますそれらと一緒に働くときに1つ。さらに多くのメソッドを追加することで、listの機能を簡単に追加できます。例えば。 popremoveinsert、および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 

使用例は、引き続き:

#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]] 
関連する問題