bool() 和 operator.truth() 有啥区别?
Posted
技术标签:
【中文标题】bool() 和 operator.truth() 有啥区别?【英文标题】:What are the differences between bool() and operator.truth()?bool() 和 operator.truth() 有什么区别? 【发布时间】:2018-08-07 04:05:45 【问题描述】:bool()
和 operator.truth()
都测试一个值是 truthy 还是 falsy 并且它们在文档中看起来非常相似,它甚至在 truth()
文档:
这相当于使用 bool 构造函数。
但是,通过简单的测试,truth()
的速度是bool()
的两倍多(显示的是 Python 3.6 时序,但 2.7 类似):
from timeit import timeit
print(timeit('bool(1)', number=10000000))
# 2.180289956042543
print(timeit('truth(1)', setup='from operator import truth', number=10000000))
# 0.7202018899843097
那么有什么区别呢?我应该使用truth()
而不是bool()
?
这个问答是在与ShadowRangerthis question 下的广泛 cmet 和讨论之后产生的。
【问题讨论】:
timeit('b(1)', 'b=bool')
明显比timeit('bool(1)')
快(尽管仍然比truth
慢得多)。查找全局名称 bool
会影响结果。
@khelwood 谢谢,好点,但时差仍然超过两倍,是吗?
是的,truth
仍然肯定比bool
快得多(顺便说一下,比True if ... else False
慢)。
@khelwood 是的,我猜if
语句是高度优化的; truth
的用例是您可以解析像 key=bool
这样的关键字参数的地方
【参考方案1】:
虽然bool()
和operator.truth()
输出对于主要用例的结果相同,但它们的实现实际上是相当不同的。 bool()
是一个类或类型构造函数,而 truth()
是一个狭窄的优化常规函数。
实际上,也有两个区别:1) bool()
不带参数调用 return
s False
而truth()
需要参数。 2) bool()
接受x
关键字参数,如bool(x=1)
,而truth()
不接受关键字参数。对于常规用例,这两种方法都会增加 bool()
的开销。
关键字实现很奇怪,因为可能没有人需要它,而且名称x
几乎没有描述性。 Issue29695 涵盖了这一点,事实上,该问题不仅影响bool()
,还影响其他类,如int()
或list()
。但是,从 Python 3.7 开始,这些关键字参数将被删除,并且速度应该会有所提高。尽管如此,我在最新的 Python 3.8 分支上测试了时间,bool()
比以前更快,但仍然比truth()
慢两倍多,这可能是由于bool()
的实现更通用。
因此,如果您的任务对速度非常重要,如果您需要函数(例如解析为sorted()
的键),我建议您使用truth()
而不是bool()
。但是,正如khelwood 指出的那样,bool()
偶尔仍然可以更快,例如filter(bool, iterable)
,因此最好为您的用例确定最佳选择的时间。
当然,如果您不需要函数而只是想测试一个值是 truthy 还是 falsy 您应该使用惯用的 if
或 @ 987654353@ 语句,最快的是 khelwood 和 user2357112 评论。
本问答是在与ShadowRanger 在this question 下进行广泛的交流和讨论之后产生的。
【讨论】:
如果您要进行微优化,以至于您会关心bool
的成本,最好只使用not not x
而不是truth(x)
。
@user2357112 速度只有一半,所以有时可能超过微优化?但是,是的,出现这种情况的上下文是一个关键功能(对于itertools.groupby)
另外,我认为filter
可能会专门针对您将bool
传递给它的情况进行优化。
@Chris_Rands 我对此的了解基本上仅限于我已经说过的内容。 =) 如果它看起来有用,请随意将其中任何一个包含在您的答案中。
@khelwood:是的,filter
has a special case for bool
that makes it treat as equivalent to passing None
(实际上并没有调用回调,而是直接调用了PyObject_IsTrue
)。所以例外情况是根本不调用bool
;如果实际调用了bool
,它总是比等效的truth
慢。 AFAICT,唯一识别这种情况的其他功能是itertools.filterfalse
;所有其他itertools
(例如takewhile
/dropwhile
)不提供这种特殊情况。以上是关于bool() 和 operator.truth() 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章