lia*_* li 5 python callable timeit
我timeit在Python中玩过,遇到了一个奇怪的问题。
我定义一个简单的函数add。 timeit当我传递add两个字符串参数时,可以工作。但是ValueError: stmt is neither a string nor callable当我传递add两个int参数时,它会增加。
>>> import timeit
>>> def add(x,y):
... return x + y
...
>>> a = '1'
>>> b = '2'
>>> timeit.timeit(add(a,b))
0.01355926995165646
>>> a = 1
>>> b = 2
>>> timeit.timeit(add(a,b))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/anaconda/lib/python3.6/timeit.py", line 233, in timeit
return Timer(stmt, setup, timer, globals).timeit(number)
File "/anaconda/lib/python3.6/timeit.py", line 130, in __init__
raise ValueError("stmt is neither a string nor callable")
ValueError: stmt is neither a string nor callable
Run Code Online (Sandbox Code Playgroud)
为什么这里的参数类型很重要?
Voi*_*ler 12
使用字符串版本 add 返回一个字符串,timeit 可以计算该字符串。所以 "12" 是一个有效的 python 表达式,而 3 不是。
timeit.timeit("12") # works
timeit.timeit(3) # does not
Run Code Online (Sandbox Code Playgroud)
使用 timeit 的最佳方法是使用 lambda 包装要测试的函数:
timeit.timeit(lambda: add(1,2))
Run Code Online (Sandbox Code Playgroud)
这比弄乱字符串要优雅得多。我真的不明白为什么所有的例子都使用字符串。
您的错误是假设Python将表达式传递add(a, b)给timeit()。并非如此,add(a, b)不是字符串,而是表达式,因此Python会执行 add(a, b),并将调用结果传递给timeit()调用。
因此,add('1', '2')结果是'12',一个字符串。将字符串传递给timeit()是可以的。但是add(1, 2)是12,一个整数。timeit(12)给你一个例外。'12'当然,计时并不是那么有趣,但这是一个有效的Python表达式,产生整数值12:
>>> import timeit
>>> def add(x,y):
... return x + y
...
>>> a = '1'
>>> b = '2'
>>> add(a, b)
'12'
>>> timeit.timeit('12')
0.009553937998134643
>>> a = 1
>>> b = 2
>>> add(a, b)
12
>>> timeit.timeit(12)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../lib/python3.7/timeit.py", line 232, in timeit
return Timer(stmt, setup, timer, globals).timeit(number)
File "/.../lib/python3.7/timeit.py", line 128, in __init__
raise ValueError("stmt is neither a string nor callable")
ValueError: stmt is neither a string nor callable
Run Code Online (Sandbox Code Playgroud)
这完全是很正常的。否则,如何将一个函数的结果直接传递给另一个函数?timeit.timeit()是只是一个Python函数,没有什么特别之处,它会禁用表达式的一般评价。
您想要的是将带有表达式的字符串传递给timeit()。timeit()不能访问您的add()函数或a或b,因此您需要使用第二个参数(设置字符串)为它提供访问权限。您可以from __main__ import add, a, b用来导入ad函数对象:
timeit.timeit('add(a,b)', 'from __main__ import add, a, b')
Run Code Online (Sandbox Code Playgroud)
现在您可以获得更有意义的结果:
>>> import timeit
>>> def add(x,y):
... return x + y
...
>>> a = '1'
>>> b = '2'
>>> timeit.timeit('add(a,b)', 'from __main__ import add, a, b')
0.16069997000158764
>>> a = 1
>>> b = 2
>>> timeit.timeit('add(a,b)', 'from __main__ import add, a, b')
0.10841095799696632
Run Code Online (Sandbox Code Playgroud)
因此,添加整数比添加字符串快。您可能想尝试使用不同大小的整数和字符串,但是添加整数将保持较快的结果。
我的问题是为什么参数类型在这里很重要?
在调用函数之前,将对函数参数进行全面评估。这意味着您执行以下操作:
timeit.timeit(add(a,b))
Run Code Online (Sandbox Code Playgroud)
然后add(a,b)就已经被timeit使用过了。因此,它没有时间。
timeit.timeit(add(a,b))当a和b是数字字符串时,“有效” 的原因只是一个愚蠢的选择:它正在计时'12'。调用的结果add('1', '2')恰好是一个有效的Python代码字符串。 timeit对其进行编译,并假定您想对文字整数12的求值时间进行计时。
| 归档时间: |
|
| 查看次数: |
3067 次 |
| 最近记录: |