当前位置:  开发笔记 > 编程语言 > 正文

在Python中将列表初始化为已知数量的元素

如何解决《在Python中将列表初始化为已知数量的元素》经验,为你挑选了5个好方法。

现在我正在使用一个列表,并期待如下:

verts = list (1000)

我应该使用数组吗?



1> Steve Losh..:

我想到的第一件事是:

verts = [None]*1000

但你真的需要预先初始化吗?


请注意,除了预先分配数组的优化之外,还有其他合法情况.它可能是使用它的代码不添加元素,只是替换现有元素,所以它更像是一个数组而不是一个列表.
这种初始化Python数组的方式是邪恶的:`a = [[]]*2; a [0] .append('foo');`现在检查`a [1]`,你会感到震惊.相比之下`a = [[] for k in range(2)]`工作正常.
不,过早优化是指当您尝试优化您不确定需要优化的代码时.您不应总是编写尽可能快的代码 - 其他问题,如业务目标,维护成本,编写工程时间,通常更为重要.
是的,这正是重点."过早优化是所有邪恶的根源"只是意味着你应该编写代码而不关心性能 - 起初.如果您发现代码稍后运行缓慢,则*然后*返回并进行类似这样的优化.
检查你的假设.例如,我目前正在分析网络错误率,方法是解析日志文件并将错误放入一个二进制数组中,目前为4个箱/小时和24小时/天.一天中的小时数不会改变,如果我更改箱/小时,我将停止并重新启动程序,所以我总是希望(目前)4*24 = 96箱.对我来说(使用C/C++/C#/等背景)开始时,将每个bin初始化为0似乎很自然.这是一个优化,是否过早?
对性能小改进的微小变化并不能证明引入的不稳定性.但是,在编写原始代码时,应始终使用性能最佳的算法编写.
我认为你错了.当您尝试更改已经有效的内容时,会发生过早优化.您应该始终尽可能编写最快的代码.
引用我的一位朋友,Peter Ritchie:"这是对误解的引用的最大误解.这是Hoare,引用的是:"我们应该忘记效率低,大约97%的时间说:过早的优化是根源所有的邪恶."意图是
即使你的短语验证我的.当您尝试优化代码时.在我的情况下,由于没有代码,显然我不能做任何过早的优化.
如果您正在编写新代码,那么这不是一个过早的优化.
1000只是一个例子.
如果你有一个图算法和少量的内存,唯一重要的是该位置是否被访问.这对很多现代的东西非常有用.

2> FoxyLad..:

不太清楚为什么每个人都给你一个很难想要这样做的事情 - 有几种情况你需要一个固定大小的初始化列表.而且你已经正确地推断出在这些情况下阵列是合理的.

import array
verts=array.array('i',(0,)*1000)

对于非pythonistas,该(0,)*1000术语是创建一个包含1000个零的元组.逗号强制python识别(0)为元组,否则将被评估为0.

我使用了元组而不是列表,因为它们通常具有较低的开销.


可悲的是,我还没有找到一个关于SO的Python问题的答案,它不包含一些自鸣得意的"你为什么要这样做?" - 将宿舍式的傲慢作为标准的回应.耶"社区".
谢谢!这个解决方案*正是我正在寻找的.在进行性能分析时,列表初始化是我的代码中的瓶颈,这使它快2倍.
我猜,有些人从字面上看是"过早"的优化.
@mikerodent Joan是世界上许多国家的男性名字,包括法国,西班牙和荷兰.

3> 小智..:

一个明显的,可能没有效率的方法是

verts = [0 for x in range(1000)]

请注意,这可以很容易地扩展到二维.例如,要获得10x100"阵列",您可以这样做

verts = [[0 for x in range(100)] for y in range(10)]



4> 小智..:

在任何编程语言中,想要初始化固定大小的数组是完全可以接受的; 它不像程序员想要在while(true)循环中放入break语句.相信我,特别是如果元素只是被覆盖而不仅仅是添加/减少,就像许多动态编程算法的情况一样,你不想乱用append语句并检查元素是否已被删除即时初始化(这是很多代码gents).

object = [0 for x in range(1000)]

这将适用于程序员正在尝试实现的目标.



5> lumbric..:

@Steve已经对你的问题给出了一个很好的答案:

verts = [None] * 1000

警告:正如@Joachim Wuttke指出的那样,必须使用不可变元素初始化列表.[[]] * 1000不会按预期工作,因为您将获得1000个相同列表的列表(类似于C中相同列表的1000个点的列表).像int,str或tuple这样的不可变对象会很好.

备择方案

调整列表大小很慢.以下结果并不令人惊讶:

>>> N = 10**6

>>> %timeit a = [None] * N
100 loops, best of 3: 7.41 ms per loop

>>> %timeit a = [None for x in xrange(N)]
10 loops, best of 3: 30 ms per loop

>>> %timeit a = [None for x in range(N)]
10 loops, best of 3: 67.7 ms per loop

>>> a = []
>>> %timeit for x in xrange(N): a.append(None)
10 loops, best of 3: 85.6 ms per loop

但是如果你没有非常大的列表,调整大小并不是很慢.None您应该考虑使用列表推导并直接使用正确的值填充列表,而不是使用单个元素(例如)和固定长度初始化列表以避免列表调整大小.例如:

>>> %timeit a = [x**2 for x in xrange(N)]
10 loops, best of 3: 109 ms per loop

>>> def fill_list1():
    """Not too bad, but complicated code"""
    a = [None] * N
    for x in xrange(N):
        a[x] = x**2
>>> %timeit fill_list1()
10 loops, best of 3: 126 ms per loop

>>> def fill_list2():
    """This is slow, use only for small lists"""
    a = []
    for x in xrange(N):
        a.append(x**2)
>>> %timeit fill_list2()
10 loops, best of 3: 177 ms per loop

比较numpy

对于庞大的数据集,numpy或其他优化的库要快得多:

from numpy import ndarray, zeros
%timeit empty((N,))
1000000 loops, best of 3: 788 ns per loop

%timeit zeros((N,))
100 loops, best of 3: 3.56 ms per loop

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有