gpt4 book ai didi

python - 什么时候 starmap 比 `List Comprehension` 更受欢迎

转载 作者:太空狗 更新时间:2023-10-29 21:21:19 28 4
gpt4 key购买 nike

在回答问题时Clunky calculation of differences between an incrementing set of numbers, is there a more beautiful way? ,我提出了两种解决方案,一种使用 List Comprehension ,另一种使用 itertools.starmap .

对我来说,list comprehension 语法看起来更清晰、更易读、不那么冗长而且更符合 Pythonic。但仍然是starmap在 itertools 中很好用,我想知道,必须有它的原因。

我的问题是什么时候 starmapList Comprehension 更受欢迎?

注意 如果它是样式问题,那么它肯定与应该有一个——最好只有一个——显而易见的方法来做到这一点相矛盾。

头对头比较

可读性很重要。 --- LC

这又是一个感知问题,但对我而言,LCstarmap 更具可读性。要使用 starmap,您需要导入 operator,或者定义 lambda 或一些显式的 multi-variable 函数和尽管如此,从 itertools 额外导入。

性能 --- LC

>>> def using_star_map(nums):
delta=starmap(sub,izip(nums[1:],nums))
return sum(delta)/float(len(nums)-1)
>>> def using_LC(nums):
delta=(x-y for x,y in izip(nums[1:],nums))
return sum(delta)/float(len(nums)-1)
>>> nums=[random.randint(1,10) for _ in range(100000)]
>>> t1=Timer(stmt='using_star_map(nums)',setup='from __main__ import nums,using_star_map;from itertools import starmap,izip')
>>> t2=Timer(stmt='using_LC(nums)',setup='from __main__ import nums,using_LC;from itertools import izip')
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=1000)/100000)
235.03 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=1000)/100000)
181.87 usec/pass

最佳答案

我通常看到的区别是 map()/starmap() 最适合您实际上只是对列表中的每个项目调用一个函数的情况。在这种情况下,它们更清晰一些:

(f(x) for x in y)
map(f, y) # itertools.imap(f, y) in 2.x

(f(*x) for x in y)
starmap(f, y)

一旦你开始需要加入 lambdafilter,你应该切换到列表 comp/generator 表达式,但在它是单一函数,对于列表理解的生成器表达式来说,语法感觉非常冗长。

它们可互换的,如果有疑问,请坚持使用生成器表达式,因为它通常更具可读性,但在简单情况下 (map(int, strings) , starmap(Vector, points)) 使用 map()/starmap() 有时可以使内容更易于阅读。

示例:

我认为 starmap() 更具可读性的示例:

from collections import namedtuple
from itertools import starmap

points = [(10, 20), (20, 10), (0, 0), (20, 20)]

Vector = namedtuple("Vector", ["x", "y"])

for vector in (Vector(*point) for point in points):
...

for vector in starmap(Vector, points):
...

对于map():

values = ["10", "20", "0"]

for number in (int(x) for x in values):
...

for number in map(int, values):
...

性能:

python -m timeit -s "from itertools import starmap" -s "from operator import sub" -s "numbers = zip(range(100000), range(100000))" "sum(starmap(sub, numbers))"                         
1000000 loops, best of 3: 0.258 usec per loop

python -m timeit -s "numbers = zip(range(100000), range(100000))" "sum(x-y for x, y in numbers)"
1000000 loops, best of 3: 0.446 usec per loop

构造一个namedtuple:

python -m timeit -s "from itertools import starmap" -s "from collections import namedtuple" -s "numbers = zip(range(100000), reversed(range(100000)))" -s "Vector = namedtuple('Vector', ['x', 'y'])" "list(starmap(Vector, numbers))"
1000000 loops, best of 3: 0.98 usec per loop

python -m timeit -s "from collections import namedtuple" -s "numbers = zip(range(100000), reversed(range(100000)))" -s "Vector = namedtuple('Vector', ['x', 'y'])" "[Vector(*pos) for pos in numbers]"
1000000 loops, best of 3: 0.375 usec per loop

在我的测试中,我们讨论的是使用简单函数(没有 lambda),starmap() 比等效的生成器表达式更快。自然地,性能应该让位于可读性,除非它已被证明是瓶颈。

lambda 如何扼杀任何性能提升的示例,与第一组中的示例相同,但使用 lambda 而不是 operator.sub():

python -m timeit -s "from itertools import starmap" -s "numbers = zip(range(100000), range(100000))" "sum(starmap(lambda x, y: x-y, numbers))" 
1000000 loops, best of 3: 0.546 usec per loop

关于python - 什么时候 starmap 比 `List Comprehension` 更受欢迎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10448486/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com