【发布时间】:2018-11-19 17:51:16
【问题描述】:
这是解决here任务的代码:
def maximizingXor(l, r):
return max([i^j for i in range(l, r+1) for j in range(i, r+1)])
这是我丑陋的解决方案:
from itertools import combinations, starmap
from operator import xor
# Complete the maximizingXor function below.
def maximizingXor(l, r):
return max(starmap(xor, combinations(range(l,r+1),2)))
它不像那个那么漂亮,但在 l=10, r=15 上确实更快:
对于我的解决方案,%timeit 显示 3.81 µs ± 156 ns,对于没有调用函数的解决方案,每个循环显示 8.67 µs ± 1.1 µs。
那么问题来了——为什么更快?
更一般地说:
在什么情况下,像 itertools 这样的函数调用比直接循环更快?
谢谢。
【问题讨论】:
-
列表推导必须为 O((r-l)**2)) 值分配内存,然后它可以遍历它们并选择最大的。你只需要恒定的内存,在生成时保留或丢弃每个值。
-
初始代码中不需要使用列表推导。生成器表达式更快吗?请注意,对于某些表达式,
map等辅助函数确实比推导式更快。 -
除了创建列表之外,
itertools构造与手写 python 版本相比可以相当快。它们在 C 中实现。 -
@VasylKolomiets 不会改变。如果你编写一个列表理解,Python 应该创建一个列表。原则上你不能优化它,因为没有什么能阻止你做
max = some_other_function你可以使用生成器表达式,但除非列表变得很大,否则可能不会更快,因为生成器很慢,而 Python 非常擅长创建事物列表。 -
理解变体创建、使用和销毁大约
r-l额外的range对象及其迭代器。 itertools 变体可以直接从一个range对象计算所有对。只需创建一个包含 5 个range对象的列表,就需要在我的机器上实现大约 90% 的初始时间差异。
标签: python performance itertools