增长python列表的最佳实践

时间:2015-07-29 17:05:20

标签: python

我有一个非常大的列表表列表,我需要添加更多列。

tbl = [range(200),range(200),range(200),...]
newCol = [val1, val2]

我看到它的方式我也可以这样做:

for idx,val in enumerate(tbl)
    tbl[idx] = newCol + val

colRep = [newCol]*len(tbl)
mgr = itertools.izip(colRep,tbl)
newTbl = [ itertools.chain(*elem) for elem in mgr]

一个人真的比另一个好吗?有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

为了便于阅读,可以使用简单的列表解析:

In [28]: tbl = [range(2),range(3),range(4)]
In [29]: [newCol + list(elt) for elt in tbl]
Out[29]: 
[['val1', 'val2', 0, 1],
 ['val1', 'val2', 0, 1, 2],
 ['val1', 'val2', 0, 1, 2, 3]]

请注意,在Python3中,range返回范围对象,而不是列表。因此,为了使代码兼容Python2和Python3,我将newCol + elt更改为newCol + list(elt)

如果您希望修改tbl 就地,可以使用

tbl[:] = [newCol + list(elt) for elt in tbl]

请注意,在我们比较性能之前,我们需要确定所需的结果,以免我们最终将苹果与橙子进行比较。

for-loop修改tbl到位。这是非常重要的吗?

zip/chain代码不会就地修改tbl而是生成一个列表 迭代器:

In [47]: newTbl
Out[47]: 
[<itertools.chain at 0x7f5aeb0a6750>,
 <itertools.chain at 0x7f5aeb0a6410>,
 <itertools.chain at 0x7f5aeb0a6310>]

这可能是你想要的,但比较性能是不公平的 这两段代码,因为iterators延迟了这个过程 枚举迭代器中的项。这就像计时一样 画房子和考虑画房子之间的区别。

为了使比较更公平,我们可以使用list来使用迭代器:

newTbl = [ list(itertools.chain(*elem)) for elem in mgr]

要对各种选项的效果进行基准测试,您可以使用timeit,如下所示:

import timeit
import itertools

tbl = [range(2),range(3),range(4)]
newCol = ['val1', 'val2']

stmt = {
    'for_loop' : '''\
for idx,val in enumerate(tbl):
    tbl[idx] = newCol + val
''',
    'list_comp': '''tbl = [newCol + elt for elt in tbl]''',
    'inplace_list_comp': '''tbl[:] = [newCol + elt for elt in tbl]''',
    'zip_chain': '''
colRep = [newCol]*len(tbl)
mgr = itertools.izip(colRep,tbl)
newTbl = [ list(itertools.chain(*elem)) for elem in mgr]
'''

}
for s in ('for_loop', 'list_comp', 'inplace_list_comp', 'zip_chain'):
    t = timeit.timeit(
        stmt[s], 
        setup='from __main__ import newCol, itertools; tbl = [range(200)]*10**5',
        number=10)
    print('{:20}: {:0.2f}'.format(s, t))

产量

for_loop            : 1.12
list_comp           : 1.21
inplace_list_comp   : 1.26
zip_chain           : 4.40

所以for_loop可能会稍快一点。请务必使用tbl进行检查 更接近你的实际用例。 timeit结果可能会有所不同 原因,包括硬件,操作系统和软件版本。

另外请注意,如果这一点很少,这可能是无意义的预优化 一段代码不是实际代码中的重要瓶颈。例如, 如果您的实际代码在此列表理解中花费1.21秒而在1000 在其他地方几秒钟,这里十分之一秒的改善是微不足道的 整体。