Python插入列表vs dict

时间:2015-08-10 22:56:02

标签: python

我编写的代码只是从数据库读取并将结果保存到python中的集合

我是第一次写的,所以这些项目存储在字典中,但后来我意识到索引只是增量的,所以我把它改为list

然而,之后程序的速度急剧下降。我首先想到的是MySQL数据库出了问题,但是在我将集合更改为dict之后,它又恢复了正常。

代码类似于:

cursor = db.cursor(pymysql.cursors.SSDictCursor)
cursor.execute('SELECT * FROM db')
coll = []  # or coll = {}
for i in cursor:
    coll.append(i)  # or coll[len(coll)] = i

我分别对coll.append()coll[len(coll)] = i进行了比较,这些线本身似乎差别不大(附加速度较慢但不足以导致剧烈放缓,这在不同的数量级上)< / p>

我认为排序可能会导致一些问题,当我使用OrderedDict时,速度似乎不会受到影响。

我想知道它是否可以基于如何实现列表和词典(可能列表必须保存在连续内存中,因此需要频繁重新分配内存,而词典不必连续),但我想知道为什么这真的发生了

编辑:

这是我正在运行的实际代码,如果简化代码缺少相关内容:

with closing(cdr_db.cursor(pymysql.cursors.SSDictCursor)) as cdr_cursor:
    cdr_cursor.execute(query.format(TABLE_NAME))

    nID_to_num = {}  # []
    num_to_nID = {}
    g = snap.TNGraph.New()

    for call in cdr_cursor:
        from_num = call['from_num']
        to_num = call['to_num']

        if from_num == 0 or to_num == 0:
            continue

        if from_num not in num_to_nID:
            curr_index = len(nID_to_num)
            g.AddNode(curr_index)
            num_to_nID[from_num] = curr_index
            nID_to_num[curr_index] = from_num  # nID_to_num.append(from_num)
        if to_num not in num_to_nID:
            curr_index = len(nID_to_num)
            g.AddNode(curr_index)
            num_to_nID[to_num] = curr_index
            nID_to_num[curr_index] = to_num  # nID_to_num.append(to_num)

        g.AddEdge(num_to_nID[from_num], num_to_nID[to_num])

这是在Windows 7中的Python 2.7 64bit中运行的。

1 个答案:

答案 0 :(得分:2)

在新代码发布后更新,Mark和Antti之间来回更新:

我相信您的原始测试用例没有显示问题的原因是,在您的原始测试用例中,您只显示使用len()作为dict案例,在您的完整示例中,您始终使用len()

在玩了一些时间之后,我发现如果我修改下面的列表示例以更紧密地匹配您的完整示例,例如coll.append(len(coll)) - 因为你在两种情况下都在计算len(),所以dict的情况更快。你的原始小例子错误地将len()的成本归因于dict版本,即使两个版本都调用了len()。

但是,(假设您在函数中执行此代码,而不是在所有查找都很昂贵的脚本级别),我发现我可以恢复那个时间并使列表比dicts更快通过在循环外预定义a = coll.append并使用它来代替。

如果这是您所看到的问题且时间紧迫,那么您可能希望在循环之外移动其他一些查找,例如len和{{1}的查找}。

**以下原始答案**

我无法验证你声称dicts比这个用例中的列表更快,所以也许你改变了别的东西。你没有指定一个版本,所以我主要使用Python 2,但使用3确定它在某些情况下是可比的。这是代码:

g.AddNode

以下是一些结果:

def usedict(times, size):
    cursor = list(range(size))
    for iteration in range(times):
        coll = {}
        for i in cursor:
            coll[len(coll)] = i


def uselist(times, size):
    cursor = list(range(size))
    for iteration in range(times):
        coll = []
        for i in cursor:
            coll.append(i)

对于较大的容器,清单显然是赢家 - 使用10e6项目的速度提高了5倍。前面提到dicts的唯一地方是Python 2.7,每个容器只有一个条目,这是一个微不足道的数量。

这是在32位Ubuntu 14.04系统上。