Python 代码优化:while还是for(或其他)?

Python 代码优化:while还是for(或其他)?,python,list,Python,List,我有这样一个列表(为了简单起见,我使用整数累进数,但它们实际上是浮动汇率): 我需要通过为第一个“off”值添加“0”,然后从“off+1”开始,值位于列表的“0”位置,将该列表“延迟”(偏移)off=3(但该数字3可能是可变的): OffsetList = [0,0,0,4,5,6,7,8,9] #__len__ = 9 我已经考虑过这两种可能的解决方案,但我对编程非常陌生,我想从一些人那里了解一下什么是最优化的解决方案,以及是否有可能开发出一种不同的解决方案,它可能比我所想的更好: #

我有这样一个列表(为了简单起见,我使用整数累进数,但它们实际上是浮动汇率):

我需要通过为第一个“off”值添加“0”,然后从“off+1”开始,值位于列表的“0”位置,将该列表“延迟”(偏移)off=3(但该数字3可能是可变的):

OffsetList = [0,0,0,4,5,6,7,8,9]   #__len__ = 9
我已经考虑过这两种可能的解决方案,但我对编程非常陌生,我想从一些人那里了解一下什么是最优化的解决方案,以及是否有可能开发出一种不同的解决方案,它可能比我所想的更好:

#SOLUTION 1
OffsetList = []
for _ in range(0,off):
    OffsetList.append(0)
for k in range(0, len(List) - off):
    OffsetList.append(List[k])

#解决方案2
偏移列表=[]
对于范围内的(0,关闭):
OffsetList.append(0)
j=0
而len(偏移列表)

您认为这两个选项中哪一个更优化(快速、安全、稳定等),为什么?另外(我肯定),有没有比我想的两个更好的解决方案

您可以使用列表切片:

>>> List = [4,5,6,7,8,9,10,11,12]
>>> off = 3
>>> OffsetList = [0]*len(List)
>>> OffsetList[off:] = List[:-off]
>>> OffsetList
[0, 0, 0, 4, 5, 6, 7, 8, 9]

对于这类事情,您可以使用列表理解:

List = [4,5,6,7,8,9,10,11,12]
off = 3
OffsetList = [0 for x in xrange(off)] + List[:-off]
print OffsetList

添加零时,最好不要显式遍历列表

def prefix1(l, offset):
    return l = [0] * offset + l

def prefix2(l, offset):
    for _ in xrange(offset):
        l.insert(0, 0)
    return l

>>> %timeit prefix1([1,2,3,4,5], 500)
10000 loops, best of 3: 4.87 µs per loop
>>> %timeit prefix2([1,2,3,4,5], 500)
10000 loops, best of 3: 190 µs per loop
旁注:我使用的是iPython
%timeit
魔术,它使用Python内置的
timeit
。您也可以直接调用time-it模块
python-m timeit--setup'n=50;l=[1,2,3,4,5]''l=[0]*n+l'
但是使用iPython会让事情变得更简单一些

一般来说,Python中的显式循环比列表理解慢,但这并不适用于所有内容,也不意味着您应该尝试将所有内容都作为列表理解编写。看见我看不出有什么理由要使用while循环,当清楚需要什么时,将
n
元素添加到列表的开头。在这种情况下,我更喜欢这样的代码:
l=[0]*offset+l
其意图非常清楚

来自JoelCornett的评论

import itertools

def prefix3(l, offset):
    return list(itertools.chain([0] * offset, l))

def prefix4(l, offset):
    return itertools.chain([0] * offset, l)

def prefix5(l, offset):
    return itertools.chain(itertools.repeat(0, offset), l)

>>> %timeit prefix3([1,2,3,4,5], 500)
10000 loops, best of 3: 13 µs per loop
>>> %timeit prefix4([1,2,3,4,5], 500)
10000 loops, best of 3: 2.9 µs per loop
>>> %timeit prefix5([1,2,3,4,5], 500)
10000 loops, best of 3: 883 ns per loop
请注意,
prefix5
的测量单位为纳秒,其他单位为微秒


prefix3
prefix4&prefix5
之间的区别在于
itertools.chain
返回一个迭代器(无随机访问,不能对其调用
len
)。因此,将其放入
prefix3
中的列表会带来开销。如果您只对元素进行迭代感兴趣,而不是通过索引访问特定的元素,则应使用
prefix5
,否则应使用
prefix2
prefix3

你是如何使用这个列表的?@JoelCornett我正在用我需要的值填充它,以便以后比较。比方说,如果第一个列表“list”包含变量“Price”,我需要偏移量列表乘以3来比较“3天前的价格和它自己的值”。因此,我们的想法是创建第三个布尔向量,它将具有
True
if
list[k]
和viceversa,这应该再现人类的行为“让我看看今天的价格是否比三天前的价格低“。使用
itertools.chain
来完成这项任务。正如我之前所说,我是编程界的新手,这个%timeit方法对我测试脚本来说是纯金。如果你能给出你对这个问题的看法来回答我的问题,我会选择这个作为我最喜欢的答案,尽管其他答案都很好。@MatteoNNZ我对这个问题的看法是什么意思?@MattiLyra,好吧,我们已经发现我想的while和for都不是好的解决方案。有些人说列表理解,有些人说列表切片。。。那么你认为什么是最好的?@MatteoNNZ我意识到
[0]*偏移量
的成本最高,因此用
itertools代替它。重复
会让事情发展得更快,请参见
prefix5
>>> l = [4,5,6,7,8,9,10,11,12]
>>> off = 3
>>> [0] * off + l[:-off]
[0, 0, 0, 4, 5, 6, 7, 8, 9]
>>> List = [4,5,6,7,8,9,10,11,12] 
>>> off = 3
>>> OffsetList = [0] * off + List[:-off]
>>> print (OffsetList)

>>> [0, 0, 0, 4, 5, 6, 7, 8, 9]
def prefix1(l, offset):
    return l = [0] * offset + l

def prefix2(l, offset):
    for _ in xrange(offset):
        l.insert(0, 0)
    return l

>>> %timeit prefix1([1,2,3,4,5], 500)
10000 loops, best of 3: 4.87 µs per loop
>>> %timeit prefix2([1,2,3,4,5], 500)
10000 loops, best of 3: 190 µs per loop
import itertools

def prefix3(l, offset):
    return list(itertools.chain([0] * offset, l))

def prefix4(l, offset):
    return itertools.chain([0] * offset, l)

def prefix5(l, offset):
    return itertools.chain(itertools.repeat(0, offset), l)

>>> %timeit prefix3([1,2,3,4,5], 500)
10000 loops, best of 3: 13 µs per loop
>>> %timeit prefix4([1,2,3,4,5], 500)
10000 loops, best of 3: 2.9 µs per loop
>>> %timeit prefix5([1,2,3,4,5], 500)
10000 loops, best of 3: 883 ns per loop