python - timeit ValueError:stmt 既不是字符串也不是可调用的
问题描述
我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
为什么参数类型在这里很重要?
解决方案
您的错误是假设 Python 将表达式传递add(a, b)
给timeit()
. 情况并非如此,add(a, b)
它不是字符串,而是一个表达式,因此 Python 会改为执行 add(a, b)
,并且该调用的结果将传递给该timeit()
调用。
所以对于add('1', '2')
结果是'12'
,一个字符串。将字符串传递给timeit()
很好。但是,add(1, 2)
是3
一个整数。timeit(3)
给你一个例外。当然,时间并不是那么'12'
有趣,但这是一个产生整数值 12 的有效 Python 表达式:
>>> 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)
3
>>> timeit.timeit(3)
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
这完全正常。否则,你怎么能将一个函数的结果直接传递给另一个函数呢?timeit.timeit()
只是另一个 Python 函数,没有什么特别的,它会禁用表达式的正常评估。
您想要的是将带有表达式的字符串传递给timeit()
. timeit()
无权访问您的add()
函数a
or b
,因此您需要使用第二个参数(设置字符串)授予它访问权限。您可以使用from __main__ import add, a, b
导入add
函数对象:
timeit.timeit('add(a, b)', 'from __main__ import add, a, b')
现在你得到更有意义的结果:
>>> 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
所以添加整数比添加字符串要快。您可能想尝试使用不同大小的整数和字符串,但添加整数仍然是更快的结果。
推荐阅读
- python - 使用 pop & insert 反转列表
- c# - Unity 使功能在特定时间段内工作
- javascript - 如果满足两个条件之一,则启用按钮
- python - 无法通过多处理加速 Python DEAP
- c++ - 如何修复 Visual Studio 的 qt 扩展?
- haskell - 难以通过 UTF8Builder 为 RIO.Logger 编写日志消息
- r - ggplot 手动图例 scale_fill_manual 用于单独的颜色因子
- firebase-cloud-messaging - Firebase FCM 协议
- javascript - jQuery AJAX 似乎没有触发
- javascript - 异步函数的问题,JS。我可以使用 Promise 吗?