2013-01-29 36 views
6

Theo this, Kích thước tối đa của danh sách Python trên hệ thống 32 bit là 536,870,912 yếu tố.Cách tạo danh sách vượt quá kích thước tối đa trong Python

Có cách nào có thể để khởi tạo danh sách có kích thước lớn hơn không?

Hãy nói rằng:

Lists
list1 = [None]*1000000000 
+3

Vâng, không có, đó là những gì một "kích thước tối đa" nghĩa là gì. Bạn có thể 'itertools.chain' một loạt các khối với nhau, tôi đoán, nếu bạn có bộ nhớ. –

+3

Bạn có tính đến mỗi phần tử của danh sách, ít nhất, chiếm 4 byte, do đó '4 * 536,870,912 = 2147483648'. Bây giờ Đó là 2GB RAM chỉ dành cho danh sách. Nếu các yếu tố không giống nhau, tôi chắc chắn bạn sẽ có được một cách MemoryError trước khi đạt đến kích thước đó. – Bakuriu

+1

@ bakuriu cảm ơn bạn đã chỉ ra điều đó. Tôi đã nhận được một MemoryError. :( –

Trả lời

10

mà lớn sẽ chiếm một số lượng lớn của không gian, vì mỗi phần tử trong danh sách sẽ chiếm ít nhất là 4 byte, vì vậy chỉ cần một danh sách với các yếu tố tối đa cho phép sẽ chiếm RAM tối thiểu 2GB . Và điều đó thậm chí không cân nhắc hệ thống 64 bit .

  1. 4 * 5.4e+8 = 2.1e+9, 2.1 GB
  2. 8 * 1.2e+18 = 9.2+18, 9.2 EB (vâng, Exabytes)

Tuy nhiên, vì lợi ích của câu hỏi, chúng ta hãy giả sử rằng bạn có rất nhiều RAM.


Một trong những tùy chọn đơn giản nhất là tạo đối tượng của riêng bạn để giữ và xử lý danh sách lớn. Về cơ bản, nó sẽ chia nhỏ danh sách khổng lồ thành các danh sách nhỏ hơn, và sau đó truy cập chúng một cách phù hợp khi cần. Vì có no real benefits of subclassing list vì bạn vẫn phải viết lại tất cả các phương thức, bạn nên tốt hơn là chỉ phân lớp object và sau đó đi từ đó. Điều duy nhất cần thiết ở đây là không bao giờ kết hợp hoặc sao chép các danh sách con (vì chúng lớn), vì vậy hãy sử dụng itertools.chain để lặp qua các danh sách khi cần thiết.

Dưới đây là một ví dụ về danh sách-phương pháp đơn giản nhất append, extend, get/setitem làm việc:

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

Ví dụ sử dụng (nếu bạn có ít hơn 4GB RAM miễn phí hoặc bạn đang ở trên một hệ thống 64-bit , thay đổi sys.maxsize trước khi cố gắng này):

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

kết quả: trong nội bộ các danh sách được chia thành nhiều danh sách, trong khi chúng xuất hiện để được ju st một khi làm việc với họ. Bạn có thể dễ dàng thêm các chức năng list bằng cách thêm các phương thức khác. Ví dụ. pop, remove, insert, và 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 

Ví dụ sử dụng, tiếp tục:

#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]] 
Các vấn đề liên quan