我有两个数字列表
list1
和 list2
,我想用相同的指令迭代它们。像这样:
for item in list1:
print(item.amount)
print(item.total_amount)
for item in list2:
print(item.amount)
print(item.total_amount)
但这感觉是多余的。我知道我可以写
for item in list1 + list2:
,但它有运行时间的代价。
有没有一种方法可以在不浪费时间的情况下做到这一点?
itertools.chain
来完成:
import itertools
l1 = [1, 2, 3, 4]
l2 = [5, 6, 7, 8]
for i in itertools.chain(l1, l2):
print(i, end=" ")
将打印:
1 2 3 4 5 6 7 8
根据文档,
chain
执行以下操作:
创建一个迭代器,从第一个可迭代对象返回元素,直到它耗尽,然后继续处理下一个可迭代对象,直到所有可迭代对象都耗尽。
itertools.chain.from_iterable
:
l = [l1, l2]
for i in itertools.chain.from_iterable(l):
print(i, end=" ")
这会产生相同的结果。
如果您不想为此导入模块,为其编写一个函数非常简单:
def custom_chain(*it):
for iterab in it:
yield from iterab
这需要 Python 3,对于 Python 2,只需
yield
使用循环将它们返回:
def custom_chain(*it):
for iterab in it:
for val in iterab:
yield val
除了前面的之外,Python
3.5
及其扩展的解包泛化,还允许在列表文字中解包:
for i in [*l1, *l2]:
print(i, end=" ")
虽然这比
l1 + l2
稍快,但它仍然构造一个列表,然后将其丢弃;仅将其作为最终解决方案。
chain
有效,但如果您觉得导入模块只是为了调用一次单个函数有点过分,您可以内联复制其行为:
for seq in (list1, list2):
for item in seq:
print(item.amount)
print(item.total_amount)
创建 (list1, list2) 元组的列表长度为 O(1),因此与将列表连接在一起相比,它的性能应该更好。
多次执行后,最快的替代方案是第二个。
import itertools
from time import time
l1 = list(range(1000))
l2 = list(range(1000))
print('Alternative 1. Itertools')
t = time()
for j in range(10000):
s = 0
for i in itertools.chain(l1, l2):
s += i
print(time() - t)
print('Alternative 2. Naive')
t = time()
for j in range(10000):
s = 0
for i in [*l1, *l2]:
s += i
print(time() - t)
print('Alternative 3. Yield')
def chain(*ls):
for l in ls:
for k in l:
yield k
t = time()
for j in range(10000):
s = 0
for i in chain(l1, l2):
s += i
print(time() - t)
这个怎么样:
for item in list1 + list2:
print(item.amount)
print(item.total_amount)
只有3行