Python for 循环从索引 1 或忽略第一个

Dur*_*nda -2 python loops python-3.x

我是 Python 的新手。我有以下代码:

>for e in entries:
     print(e)
Run Code Online (Sandbox Code Playgroud)

但是如何忽略条目中的第一个元素?

我想从索引 1 而不是 0 进行迭代,并迭代到最后一个元素。

wiz*_*zz4 5

有几种方法可以做到这一点。

  1. for e in entries[1:]:
        print(e)
    
    Run Code Online (Sandbox Code Playgroud) 此方法创建一个包含entries除第一个之外的所有元素的新列表,然后对其进行迭代。它最清晰易读,但仅适用于lists(和tuples)并且具有复制列表的所有问题。
  2. iterator = iter(entries)
    next(iterator)
    for e in iterator:
        print(e)
    
    Run Code Online (Sandbox Code Playgroud) 此方法创建一个迭代器,丢弃第一项,然后对其进行迭代。这可能是执行此操作的最快方法,* 但它不是很容易阅读。
  3. for i, e in enumerate(entries):
        if i > 0:  # or, if i:
            print(e)
    
    Run Code Online (Sandbox Code Playgroud) 这种方法根本不是很快,但比第二种方法更容易阅读。它可能比第一个更糟糕,除非您出于某种原因真的不想制作列表的副本。
  4. import itertools
    ...
    for e in itertools.islice(entries, 1, None):
        print(e)
    
    Run Code Online (Sandbox Code Playgroud) 这是 2 的版本,具有 1 的所有可读性优势。我想说这可能是最好的方法,但使用 1 是最安全的,因为这是人们所期望的。

*:在您使用timeit.timeit(来自timeit模块)测试代码之前,速度不应成为问题

为了测试这一点,我写了一个骇人听闻的测试套件:

import timeit

for i, setup in enumerate(("import itertools\nentries=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", "import itertools\nentries=list(range(1000))", """import itertools
def primes():
    l = [2]
    for n in range(3,1000):
        for prime in l:
            if n % prime != 0:
                break
        else:
            yield n
            l.append(n)
entries=primes()""")):
    for j, stmt in enumerate(("""for e in entries[1:]:
    pass""", """iterator = iter(entries)
next(iterator)
for e in iterator:
    pass""", """for i, e in enumerate(entries):
    if i > 0:
        pass""", """for e in itertools.islice(entries, 1, None):
    pass""")):
        try:
            time = timeit.timeit(stmt=stmt, setup=setup)
        except:
            print(i, j, "DOES NOT WORK")
        else:
            print(i, j, time)
Run Code Online (Sandbox Code Playgroud)

这输出:

0 0 0.7670026040000266
0 1 0.7781598509996002
0 2 1.794472709999809
0 3 0.9263826839996909
1 0 35.545838756000194
1 1 29.032120127000326
1 2 145.82462093200002
1 3 40.03643834500008
2 0 DOES NOT WORK
2 1 DOES NOT WORK
2 2 0.5132426549998854
2 3 0.490669440000147
Run Code Online (Sandbox Code Playgroud)

与所有这些事情一样,结果并不是我所期望的。这就是为什么您在测试之前从不进行优化!

对于小输入

对于小输入 ( [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),第一种方法 ( slice) 最快。这是因为创建另一个列表的成本被更少的字节码(基本上,更少的代码)所节省的成本所抵消。next由于其效率,紧随其后的是第二种方法 ( ),然后是第三种方法 ( enumerate),因为它有一个额外的嵌套迭代器。最后也是最不重要的是第四个方法 ( islice),因为它有一个额外的嵌套迭代器来执行一个重要的功能(模拟切片)。

对于大输入

对于大输入 ( list(range(1000))),next最快(因为优化)其次是slice,其次是islice。然后我睡着了。然后终于 enumerate完成了。这可能是因为列表比 长256,所以 Python 必须创建新的整数对象来enumerate为它们编号。说来话长。

对于发电机输入

对于生成器输入 ( primes()),slice不起作用。但是,我的测试代码是错误的,导致next了不应该出错的错误,所以我不能告诉你哪个最快。对不起!

但这可能是最好的,因为timeit.timeit运行1000000迭代并且我的主要计算器功能太慢了,以至于在我有生之年都无法完成。

一切都很好,结局很好,对吧?