Python插入列表与dict

Python插入列表与dict,python,Python,我编写的代码只需从数据库中读取数据,并将结果保存到python中的集合中 我首先写的是,项目存储在字典中,但后来我意识到索引只是增量的,所以我将其更改为列表 然而在那之后,程序的速度急剧下降。我最初认为MySQL数据库有问题,但在我将集合更改为dict后,它又恢复了正常 代码类似于: cursor = db.cursor(pymysql.cursors.SSDictCursor) cursor.execute('SELECT * FROM db') coll = [] # or coll =

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

我首先写的是,项目存储在字典中,但后来我意识到索引只是增量的,所以我将其更改为
列表

然而在那之后,程序的速度急剧下降。我最初认为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
,这些行本身似乎没有太大差异(append速度较慢,但不足以导致显著的减速,其幅度不同)

我认为订购可能会引起一些问题,当我使用
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 64位运行的。

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

我相信您的原始测试用例没有显示问题的原因是,在您的原始测试用例中,您只显示了对dict用例使用
len()
,而在您的完整示例中,您总是使用
len()

在进一步研究计时之后,我发现如果我修改下面的列表示例,使其与完整示例更加匹配,例如
coll.append(len(coll))
——因为您在这两种情况下都在计算len(),那么dict的速度更快。您最初的小示例错误地将len()的成本归因于dict版本,尽管两个版本都调用了len()

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

如果这是您正在看到的问题,并且时间紧迫,那么您可能希望将一些其他查找移到循环之外,例如
len
g.AddNode
的查找

**原始答案如下**

我无法证实您的说法,即在本用例中,dict比列表更快,所以您可能更改了其他内容。您没有指定版本,所以我主要使用Python2,但使用3来确定它在某些情况下具有可比性。代码如下:

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)
以下是一些结果:

$ python -m timeit "import listdict;listdict.uselist(10, 100000)"
10 loops, best of 3: 49.7 msec per loop
$ python -m timeit "import listdict;listdict.usedict(10, 100000)"
10 loops, best of 3: 103 msec per loop
$ python3 -m timeit "import listdict;listdict.uselist(10, 100000)"
10 loops, best of 3: 65.9 msec per loop
$ python3 -m timeit "import listdict;listdict.usedict(10, 100000)"
10 loops, best of 3: 131 msec per loop
$ python -m timeit "import listdict;listdict.uselist(1, 10000000)"
10 loops, best of 3: 666 msec per loop
$ python -m timeit "import listdict;listdict.usedict(1, 10000000)"
10 loops, best of 3: 3.66 sec per loop
$ python -m timeit "import listdict;listdict.uselist(100000, 10)"
10 loops, best of 3: 69.6 msec per loop
$ python -m timeit "import listdict;listdict.usedict(100000, 10)"
10 loops, best of 3: 82.1 msec per loop
$ python -m timeit "import listdict;listdict.uselist(100000, 4)"
10 loops, best of 3: 29.4 msec per loop
$ python -m timeit "import listdict;listdict.usedict(100000, 4)"
10 loops, best of 3: 34.4 msec per loop
$ python -m timeit "import listdict;listdict.uselist(1000000, 1)"
10 loops, best of 3: 151 msec per loop
$ python -m timeit "import listdict;listdict.usedict(1000000, 1)"
10 loops, best of 3: 148 msec per loop
$ python3 -m timeit "import listdict;listdict.uselist(1000000, 1)"
10 loops, best of 3: 177 msec per loop
$ python3 -m timeit "import listdict;listdict.usedict(1000000, 1)"
10 loops, best of 3: 213 msec per loop
$ python -m timeit "import listdict;listdict.uselist(1000000, 3)"
10 loops, best of 3: 245 msec per loop
$ python -m timeit "import listdict;listdict.usedict(1000000, 3)"
10 loops, best of 3: 272 msec per loop
对于更大的容器,列表是一个明显的赢家——10e6个项目的速度快了5倍。dicts唯一领先的地方是Python2.7,每个容器只有一个条目,数量很少


这是一个32位Ubuntu 14.04系统。

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

我相信您的原始测试用例没有显示问题的原因是,在您的原始测试用例中,您只显示了对dict用例使用
len()
,而在您的完整示例中,您总是使用
len()

在进一步研究计时之后,我发现如果我修改下面的列表示例,使其与完整示例更加匹配,例如
coll.append(len(coll))
——因为您在这两种情况下都在计算len(),那么dict的速度更快。您最初的小示例错误地将len()的成本归因于dict版本,尽管两个版本都调用了len()

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

如果这是您正在看到的问题,并且时间紧迫,那么您可能希望将一些其他查找移到循环之外,例如
len
g.AddNode
的查找

**原始答案如下**

我无法证实您的说法,即在本用例中,dict比列表更快,所以您可能更改了其他内容。您没有指定版本,所以我主要使用Python2,但使用3来确定它在某些情况下具有可比性。代码如下:

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)
以下是一些结果:

$ python -m timeit "import listdict;listdict.uselist(10, 100000)"
10 loops, best of 3: 49.7 msec per loop
$ python -m timeit "import listdict;listdict.usedict(10, 100000)"
10 loops, best of 3: 103 msec per loop
$ python3 -m timeit "import listdict;listdict.uselist(10, 100000)"
10 loops, best of 3: 65.9 msec per loop
$ python3 -m timeit "import listdict;listdict.usedict(10, 100000)"
10 loops, best of 3: 131 msec per loop
$ python -m timeit "import listdict;listdict.uselist(1, 10000000)"
10 loops, best of 3: 666 msec per loop
$ python -m timeit "import listdict;listdict.usedict(1, 10000000)"
10 loops, best of 3: 3.66 sec per loop
$ python -m timeit "import listdict;listdict.uselist(100000, 10)"
10 loops, best of 3: 69.6 msec per loop
$ python -m timeit "import listdict;listdict.usedict(100000, 10)"
10 loops, best of 3: 82.1 msec per loop
$ python -m timeit "import listdict;listdict.uselist(100000, 4)"
10 loops, best of 3: 29.4 msec per loop
$ python -m timeit "import listdict;listdict.usedict(100000, 4)"
10 loops, best of 3: 34.4 msec per loop
$ python -m timeit "import listdict;listdict.uselist(1000000, 1)"
10 loops, best of 3: 151 msec per loop
$ python -m timeit "import listdict;listdict.usedict(1000000, 1)"
10 loops, best of 3: 148 msec per loop
$ python3 -m timeit "import listdict;listdict.uselist(1000000, 1)"
10 loops, best of 3: 177 msec per loop
$ python3 -m timeit "import listdict;listdict.usedict(1000000, 1)"
10 loops, best of 3: 213 msec per loop
$ python -m timeit "import listdict;listdict.uselist(1000000, 3)"
10 loops, best of 3: 245 msec per loop
$ python -m timeit "import listdict;listdict.usedict(1000000, 3)"
10 loops, best of 3: 272 msec per loop
对于更大的容器,列表是一个明显的赢家——10e6个项目的速度快了5倍。dicts唯一领先的地方是Python2.7,每个容器只有一个条目,数量很少


这是一个32位Ubuntu 14.04系统。

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

我相信您的原始测试用例没有显示问题的原因是,在您的原始测试用例中,您只显示了对dict用例使用
len()
,而在您的完整示例中,您总是使用
len()

在进一步研究计时之后,我发现如果我修改下面的列表示例,使其与完整示例更加匹配,例如
coll.append(len(coll))
——因为您在这两种情况下都在计算len(),那么dict的速度更快。您最初的小示例错误地将len()的成本归因于dict版本,尽管两个版本都调用了len()

但是,(假设您是在函数中执行此代码,而不是在脚本级别执行此代码,因为所有查找都是昂贵的),我发现我可以