我正在尝试优化我的Python 2.7.x代码。我将在for循环中执行一个操作,可能需要数百万次,所以我希望它尽可能快。
我的操作是获取10个字符串的列表并将它们转换为2个整数,然后是8个浮点数。
以下是我尝试的MWE:
import timeit
words = ["1"] * 10
start_time = timeit.default_timer()
for ii in range(1000000):
values = map(float, words)
values[0] = int(values[0])
values[1] = int(values[1])
print "1", timeit.default_timer() - start_time
start_time = timeit.default_timer()
for ii in range(1000000):
values = map(int, words[:2]) + map(float, words[2:])
print "2", timeit.default_timer() - start_time
start_time = timeit.default_timer()
local_map = map
for ii in range(1000000):
values = local_map(float, words)
values[0] = int(values[0])
values[1] = int(values[1])
print "3", timeit.default_timer() - start_time
1 2.86574220657
2 3.83825802803
3 2.86320781708
第一段代码是我管理过的最快的代码。 map
函数似乎比使用列表理解快得多。但是仍有一些冗余,因为我将所有内容映射到一个浮点数,然后将前两个项目更改为整数。
有没有比我的代码更快的东西?
为什么不使地图功能本地化local_map = map
,提高第三代码块的速度?
答案 0 :(得分:0)
我还没有找到更快的东西,但在某些情况下,你最快的代码实际上会出错。问题是,Python float
(它是一个C double)的精度有限,对于超过2 ** 53
的值(IIRC;可能在位数上偏离一个),它不能代表所有整数值。相比之下,Python int
是任意精度;如果你有记忆,它可以有效地代表无限的价值。
您想要改变:
values[0] = int(values[0])
values[1] = int(values[1])
为:
values[0] = int(words[0])
values[1] = int(words[1])
要避免这种情况。重新分析会使这更依赖于被解析的字符串的长度(因为对于更长的输入,多次转换会花费更多)。
至少在我的Python(3.5)上工作得相当快的另一种方法是预构建转换器集,以便您可以直接调用正确的函数。例如:
words = ["1"] * 10
converters = (int,) * 2 + (float,) * 8
values = [f(v) for f, v in zip(converters, words)]
您希望使用zip
的两个版本进行测试,看看基于list
的生成器itertools.izip
生成版本是否更快(对于像这样的短输入,我真的可以&#39 ; t)。在Python 3.5中(其中zip
始终是像Py2' s itertools.izip
一样的生成器),这比相同输入的最快解决方案花了大约10%(我使用了min()
timeit.repeat
运行而不是您使用的手动滚动版本;如果输入更大,它可能会做得更好(因此解析两次会更贵)。