簡體   English   中英

python列表列表的內存消耗

[英]Memory consumption of python lists of lists

我最近正在研究的一個代碼被發現使用大約200MB的內存來運行,我很難過為什么它需要這么多。

基本上它將一個文本文件映射到一個列表中,其中文件中的每個字符都是它自己的列表,其中包含該字符以及它到目前為止(從零開始)顯示為兩個項目的頻率。

所以'abbac...'會是[['a','0'],['b','0'],['b','1'],['a','1'],['c','0'],...]

對於長度為100萬個字符的文本文件,它使用了200MB。

這是合理的還是我的代碼正在做的其他事情? 如果它是合理的,是不是因為列表數量很多? [a,0,b,0,b,1,a,1,c,0...]會占用更少的空間嗎?

如果您不需要列表本身,那么我完全贊同@ Lattyware使用生成器的解決方案。

但是,如果這不是一個選項,那么您可以通過僅存儲文件中每個字符的位置來壓縮列表中的數據而不會丟失信息。

import random
import string

def track_char(s):
    # Make sure all characters have the same case
    s = s.lower()
    d = dict((k, []) for k in set(s))
    for position, char in enumerate(s):
         d[char].append(position)
    return d

st = ''.join(random.choice(string.ascii_uppercase) for _ in range(50000))
d = track_char(st)

len(d["a"])

# Total number of occurrences of character 2
for char, vals in d.items():
    if 2 in vals:
         print("Character %s has %s occurrences" % (char,len(d[char]))
Character C has 1878 occurrences

# Number of occurrences of character 2 so far
for char, vals in d.items():
    if 2 in vals:
        print("Character %s has %s occurrences so far" % (char, len([x for x in d[char] if x <= 2))
Character C has 1 occurrences so far

這樣,每次出現時都不需要復制字符串,並且可以保留所有出現的信息。

要比較原始列表或此方法的對象大小,這是一個測試

import random
import string
from sys import getsizeof

# random generation of a string with 50k characters
st = ''.join(random.choice(string.ascii_uppercase) for _ in range(50000))

# Function that returns the original list for this string
def original_track(s):
    l = []
    for position, char in enumerate(s):
        l.append([char, position])
    return l

# Testing sizes
original_list = original_track(st)
dict_format = track_char(st)

getsizeof(original_list)
406496
getsizeof(dict_format)
1632

如您所見,dict_format的大小約為250倍。 然而,這種尺寸差異應該在更大的字符串中更明顯。

在內存使用和列表方面,減少內存使用的最佳方法之一就是完全避免使用列表 - Python以生成器的形式支持迭代器。 如果你可以生成一個生成器而不是構建一個列表,你應該可以用很少的內存使用來做這樣的事情。 當然,這取決於你之后對數據做了什么(比如說你把這個結構寫到文件中,你可以一塊一塊地做,而不是一次性存儲整個文件)。

from collections import Counter

def charactersWithCounts():
    seen = Counter()
    for character in data:
        yield (character, seen[character])
        seen[character] += 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM