timeit.timeit方法错误“预期缩进块”

时间:2017-01-07 21:20:25

标签: python python-3.x timeit

当我学习Python 3.5时,我想开始比较不同代码的时间。 我已经在其他一些简单的语句中尝试了timeit.timeit模块并使其工作。

我无法让它处理以下代码并得到以下错误:

Traceback (most recent call last):
File "C:\Users\ASUS\Desktop\pythoncode\class_gen.py", line 10, in <module>
    print(timeit.timeit(",".join(["#"+i+j for i in listTags for j in listTags if i != j])))
  File "C:\Python35\lib\timeit.py", line 213, in timeit
    return Timer(stmt, setup, timer, globals).timeit(number)
  File "C:\Python35\lib\timeit.py", line 133, in __init__
    code = compile(src, dummy_src_name, "exec")
  File "<timeit-src>", line 7
    _t1 = _timer()
      ^
IndentationError: expected an indented block"""

我使用的代码是:

import itertools
import timeit

listTags = [ "TOT" , "WBA", "BUR", "SOU"]

print(timeit.timeit(",".join(["#" + "".join(t) for t in itertools.permutations(listTags, 2)]))

print(timeit.timeit(",".join(["#"+i+j for i in listTags for j in listTags if i != j])))

我在使用和不使用number=number关键字的情况下尝试过它都无济于事。

2 个答案:

答案 0 :(得分:2)

您必须在timeit调用中将python代码作为字符串传递。

您正在传递要执行的表达式(#TOTWBA,#TOTBUR,#TOTSOU,#WBATOT,#WBABUR,#WBASOU,#BURTOT,#BURWBA,#BURSOU,#SOUTOT,#SOUWBA,#SOUBUR)的已计算值。

此外,您必须按字面意思传递listTags或使用setup表达式,因为timeit在不同的解释器中运行:它不知道您之前定义的变量。

我使用单引号重写了第一个timeit调用以保护您的语句,并添加了setup调用来定义listTags变量。

import itertools
import timeit

print(timeit.timeit('",".join(["#" + "".join(t) for t in itertools.permutations(listTags, 2)])',setup='listTags = [ "TOT" , "WBA", "BUR", "SOU"]'))

我得到一个时间:5.2231671576142285:它正在工作

答案 1 :(得分:2)

@Jean是正确的,您需要将其作为字符串传递给timeit(用单引号'包装),以使其正常工作。您还需要传递适当的setup名称查找才能成功。

然而,有趣的是要注意为什么会发生这种情况。

当您尝试timeit时:

print(timeit.timeit(",".join(["#" + "".join(t) for t in itertools.permutations(listTags, 2)]))

你应该意识到论证得到了评估。最终使用参数调用timeit

timeit.timeit('#TOTWBA,#TOTBUR,#TOTSOU,#WBATOT,#WBABUR,#WBASOU,#BURTOT,#BURWBA,#BURSOU,#SOUTOT,#SOUWBA,#SOUBUR')

timeit内,将其格式化为定时的默认模板;很容易重新创建该模板以查看Python尝试执行的内容:

template = """
def inner(_it, _timer{init}):
    {setup}
    _t0 = _timer()
    for _i in _it:
        {stmt}
    _t1 = _timer()
    return _t1 - _t0
"""  
src = template.format(stmt=",".join(["#"+i+j for i in listTags for j in listTags if i != j]), setup='', init='')

因此,获得exec的是:

>>> print(src)
def inner(_it, _timer):

    _t0 = _timer()
    for _i in _it:
        #TOTWBA,#TOTBUR,#TOTSOU,#WBATOT,#WBABUR,#WBASOU,#BURTOT,#BURWBA,#BURSOU,#SOUTOT,#SOUWBA,#SOUBUR
    _t1 = _timer()
    return _t1 - _t0

如果你尝试在REPL中正常执行,那么会导致IndentationError,因为for循环只在其正文中有一个注释(在解析过程中会被删除)。执行:

for i in [1, 2]:
    # foo
print('fooing')

结果:

  File "<ipython-input-58-634beff715a1>", line 3
    print('fooing')
        ^
IndentationError: expected an indented block