Dur*_*nda -2 python loops python-3.x
我是 Python 的新手。我有以下代码:
>for e in entries:
print(e)
Run Code Online (Sandbox Code Playgroud)
但是如何忽略条目中的第一个元素?
我想从索引 1 而不是 0 进行迭代,并迭代到最后一个元素。
有几种方法可以做到这一点。
for e in entries[1:]:
print(e)
Run Code Online (Sandbox Code Playgroud)
此方法创建一个包含entries除第一个之外的所有元素的新列表,然后对其进行迭代。它最清晰易读,但仅适用于lists(和tuples)并且具有复制列表的所有问题。iterator = iter(entries)
next(iterator)
for e in iterator:
print(e)
Run Code Online (Sandbox Code Playgroud)
此方法创建一个迭代器,丢弃第一项,然后对其进行迭代。这可能是执行此操作的最快方法,* 但它不是很容易阅读。for i, e in enumerate(entries):
if i > 0: # or, if i:
print(e)
Run Code Online (Sandbox Code Playgroud)
这种方法根本不是很快,但比第二种方法更容易阅读。它可能比第一个更糟糕,除非您出于某种原因真的不想制作列表的副本。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迭代并且我的主要计算器功能太慢了,以至于在我有生之年都无法完成。
一切都很好,结局很好,对吧?
| 归档时间: |
|
| 查看次数: |
3739 次 |
| 最近记录: |