更新:为发布steveha 更早的答案的副本而道歉。大量谈论我的阅读技巧。现在仍然将这个答案留在网上,只是因为我对 i/o/buffering/runtime 效果的思考。
原帖:
我无法相信 Python 应用一个正则表达式并计算一个平方根所需的时间比从标准输入读取一行并在标准输出(或任何 I/O 上)输出结果所需的时间更长。
由于某个时间点的 I/O 将来自一个硬盘驱动器,并且会转到另一个硬盘驱动器或用户的眼睛,这应该是限制因素。
I/O 通常被缓冲以提高速度。通常一个缓冲区被突发填充,然后 cpu 在等待设备提供更多数据时空闲。
这会为您的应用程序生成一个生成器。编写一个生成器,逐行读取输入,并立即按需提供一个 sqrt 数。我怀疑这会比任何合理的现代硬件上的整体 I/O 速度慢。如果您使用的是特殊设备(如嵌入式、uController、Raspberry Pi 等,请告诉我们)
您可以做的一项优化是预编译正则表达式。当您对每个测试使用相同的正则表达式时,让我们只解析一次正则表达式。您在问题中的示例很好,因为您正在执行re.findall()
. 我只是为其他读者详细说明。
import sys, re, math
pattern = re.compile(r'\b\d+\b')
def fh_numbers_to_sqrt(fh):
for line in fh:
for i in re.findall(pattern, line):
yield math.sqrt(float(i))
numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in numbers_g:
print('%.4f' % num)
这允许所有正则表达式和数学运算与 I/O 时间交错。
现在,我们根本无法真正优化和集成的一件事是reverse
. 该算法必须等到最后一个元素才能反转。
所以我们可以把调用代码改成:
numbers_g = fh_numbers_to_sqrt(sys.stdin)
for num in reverse(list(numbers_g)):
print('%.4f' % num)
并希望这比你原来拥有的更快。同样,这应该更快的唯一原因是因为我们已经将正则表达式解析和计算的运行时间隐藏在从标准输入读取数据所需的挂钟时间内。这仍应受 I/O 限制。实际上,这reverse
可能不会真正增加整体运行时间,因为它可能会与标准输出上发生的 I/O 交错。看看挂钟,这个算法可能根本不会用完任何时间。:-)
To prove or negate my whole post, you could measure with time.time()
how long it takes from the start of your script to just before the line Data = re.findall
, and from then on to the end. If I'm correct then the data reading will take most of the time. If not, it's worthwhile to measure also the time required for all the regular expression searches. Let us know. I'm curious...