2

我习惯用 C/C++ 编写代码,当我看到以下数组操作时,我觉得有些 CPU 浪费:

version = '1.2.3.4.5-RC4'                 # the end can vary a lot
api = '.'.join( version.split('.')[0:3] ) # extract '1.2.3'

因此我想知道:

  • 这条线是否会被执行(解释)为创建一个临时数组(内存分配),然后连接前三个单元格(再次分配内存)?
    还是 python 解释器足够聪明?
    (我也很好奇PythranParakeetNumbaCython和其他 python 解释器/编译器在这种情况下所做的优化......)

  • 是否有一个技巧可以编写更高效的 CPU 并且仍然可以理解/优雅的替换行?
    (您可以提供特定的 Python2 和/或 Python3 技巧和提示)

4

3 回答 3

2

为此,我不知道 CPU 的使用情况,但这不就是我们以某种方式使用高级语言的原因吗?

另一种解决方案是使用正则表达式,使用编译模式应该允许后台优化:

import re
version = '1.2.3.4.5-RC4'
pat = re.compile('^(\d+\.\d+\.\d+)')
res = re.match(version)
if res:
  print res.group(1)

编辑:正如@jonrsharpe 建议的那样,我也运行了timeit基准测试。这是我的结果:

def extract_vers(str):
   res = pat.match(str)
   if res:
     return res.group(1)
   else:
     return False

>>> timeit.timeit("api1(s)", setup="from __main__ import extract_vers,api1,api2; s='1.2.3.4.5-RC4'")
1.9013631343841553
>>> timeit.timeit("api2(s)", setup="from __main__ import extract_vers,api1,api2; s='1.2.3.4.5-RC4'")
1.3482811450958252
>>> timeit.timeit("extract_vers(s)", setup="from __main__ import extract_vers,api1,api2; s='1.2.3.4.5-RC4'")
1.174590826034546

编辑:但无论如何,Python中存在一些lib,例如distutils.version完成这项工作。你应该看看那个答案

于 2014-12-02T10:58:11.050 回答
2

回答您的第一个问题:不,解释器不会对此进行优化。Python 将从字符串创建一个列表,然后为切片创建第二个列表,然后将列表项重新组合成一个新字符串。

为了涵盖第二个,您可以通过split使用可选maxsplit参数限制来稍微优化它:

>>> v = '1.2.3.4.5-RC4'
>>> v.split(".", 3)
['1', '2', '3', '4.5-RC4']

一旦找到第三个'.',Python 就会停止搜索字符串。您还可以通过删除0切片的默认参数来稍微整理一下:

api = '.'.join(version.split('.', 3)[:3])

但是请注意,性能上的任何差异都可以忽略不计:

>>> import timeit
>>> def test1(version):
    return '.'.join(version.split('.')[0:3])

>>> def test2(version):
    return '.'.join(version.split('.', 3)[:3])

>>> timeit.timeit("test1(s)", setup="from __main__ import test1, test2; s = '1.2.3.4.5-RC4'")
1.0458565345561743
>>> timeit.timeit("test2(s)", setup="from __main__ import test1, test2; s = '1.2.3.4.5-RC4'")
1.0842980287537776

maxsplit更长的字符串包含更多不相关的 s的好处变得更明显'.'

>>> timeit.timeit("s.split('.')", setup="s='1.'*100")
3.460900054011617
>>> timeit.timeit("s.split('.', 3)", setup="s='1.'*100")
0.5287887450379003
于 2014-12-02T11:06:03.333 回答
0

我习惯用 C/C++ 编写代码,当我看到以下数组操作时,我觉得有些 CPU 浪费:

对于面对 python 代码的 C/C++ 程序员来说,CPU 浪费的感觉是绝对正常的。你的代码:

version = '1.2.3.4.5-RC4'                 # the end can vary a lot
api = '.'.join(version.split('.')[0:3])   # extract '1.2.3'

在python 中绝对没问题,没有可能的简化。仅您必须执行 1000 次时,才考虑使用库函数编写自己的.

于 2014-12-02T11:35:04.227 回答