你不需要map 来做类似的事情,事实上通过使用列表理解可以获得可读性:
>>> [RPS_winner(a, b) for a, b in rounds]
[1, 2, 2, 2, 0, 1, 1, 2, 0, 1]
另一种可能性是使用专门为此设计的itertools.starmap:
from itertools import starmap
list(starmap(RPS_winner, rounds))
当然,您也可以手动完成:
list(map(lambda ab: RPS_winner(*ab), rounds)
如果您打算在很长的rounds 列表中使用它,将其重写为:
def RPS_winner_star(ab):
return RPS_winner(*ab)
list(map(RPS_winner_star, rounds))
注意
请求使用map 等的正当理由是rounds 实际上不是一个列表,而是另一个迭代器。在这种情况下,很高兴获得一个新的迭代器,它会在不列出列表的情况下以rounds 的形式输出获胜者。例如,您可以将生成的迭代器“管道”到Counter:
irounds = generate_rounds(n=1_000_000) # a generator
iwinner = map(RPS_winner_star, irounds)
score_board = Counter(iwinner)
这是一个完整的例子和时间安排:
(注意:generate_rounds 生成器现在可以预见地重复,以减少其自身在整体测量中的时间;我们现在还减去在时间比较中花费在生成器中的时间结束)。
import random
from collections import Counter
from itertools import starmap
def generate_rounds(n):
choices = list('RPS')
m = len(choices)
for k in range(n):
i = k % m
j = (k // m) % m
yield choices[i], choices[j]
def f_onlygen(n):
for _ in generate_rounds(n):
pass
def f_map(n):
irounds = generate_rounds(n) # a generator
iwinner = map(RPS_winner_star, irounds)
return Counter(iwinner)
def f_starmap(n):
irounds = generate_rounds(n) # a generator
iwinner = starmap(RPS_winner, irounds)
return Counter(iwinner)
def f_listmap(n):
rounds = list(generate_rounds(n))
winner = list(map(RPS_winner_star, rounds))
return Counter(winner)
def f_listcomprehension(n):
rounds = list(generate_rounds(n))
winner = [RPS_winner(a, b) for a, b in rounds]
return Counter(winner)
def f_comprehension(n):
irounds = generate_rounds(n)
winner = [RPS_winner(a, b) for a, b in rounds]
return Counter(winner)
测量:
n = 1_000_000
t = {}
t['onlygen'] = %timeit -o f_onlygen(n)
t['map'] = %timeit -o f_map(n)
t['starmap'] = %timeit -o f_starmap(n)
t['listmap'] = %timeit -o f_listmap(n)
t['listcomprehension'] = %timeit -o f_listcomprehension(n)
t['comprehension'] = %timeit -o f_comprehension(n)
结果:
res = sorted([
(k, v.average, v.average - t['onlygen'].average)
for k, v in t.items()
], key=lambda tup: tup[2])
print(f'{"name":<17} {"total":<6} above onlygen')
for name, tot, rel in res:
print(f'{name:<17} {tot*1000:3.0f} ms, {rel*1000:3.0f} ms')
name total above onlygen
onlygen 172 ms, 0 ms
comprehension 235 ms, 62 ms
starmap 376 ms, 204 ms
map 432 ms, 260 ms
listcomprehension 470 ms, 298 ms
listmap 482 ms, 310 ms