bool()和operator.truth()有什么区别?

16

bool()operator.truth() 都用于测试值是否为真或假,从文档上看它们似乎非常相似,在 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()吗?

这个问答是在与ShadowRanger这个问题下进行广泛评论和讨论后产生的。


1
timeit('b(1)', 'b=bool')timeit('bool(1)')明显更快(尽管仍然比truth慢得多)。查找全局名称bool会影响结果。 - khelwood
@khelwood 谢谢,观点很好,但时间差仍然是两倍以上,对吧? - Chris_Rands
1
是的,truth仍然比bool快得多(顺便说一句,它比True if ... else False慢)。 - khelwood
@khelwood 是的,我猜if语句是高度优化的;truth的用例是当您解析关键字参数时,例如key=bool - Chris_Rands
1个回答

13

虽然 bool()operator.truth() 在大多数使用情况下输出相同的结果,但它们的实现方式实际上有很大不同。 bool() 是一个类或类型构造函数,而truth()是一个窄化优化的常规函数。

在实践中,也有两个区别:1)没有参数调用 bool() 会返回 False,而 truth() 需要一个参数。2)bool() 接受一个 x 关键字参数,例如 bool(x=1),而 truth() 不接受关键字参数。这两者都增加了 bool() 在常规用例中的开销。

关键字实现方法很奇怪,因为可能没有人需要它,而且名称 x 并不具有描述性。问题号为 Issue29695,事实上这个问题不仅影响 bool(),还涉及到其他诸如 int()list() 的类。然而,从 Python 3.7 开始,这些关键字参数将被删除,并且速度应该会提高。尽管如此,我在最新的 Python 3.8 分支上测试了时间,bool() 比以前更快,但仍然比 truth() 慢两倍以上,这可能是由于 bool() 的更通用的实现。

因此,如果您有一个速度很重要的任务,我建议在需要函数时使用 truth() 而不是 bool()(例如解析为 sorted() 的键)。然而,正如 khelwood 指出的那样,bool() 有时仍然可能更快,例如 filter(bool, iterable),因此最好根据实际情况计时来确定最佳选项。

当然,如果你不需要一个函数而只是想测试一个值是否为真或假,那么应该使用惯用的ifif not语句进行,这是最快的方法,正如khelwood和user2357112所评论的。

这个问答是在与ShadowRanger的广泛评论和讨论后产生的,在这个问题下。


如果你在进行微观优化时关注于 bool 类型的成本,那么使用 not not x 而不是 truth(x) 更好。 - user2357112
1
@user2357112 嗯,它的速度只有一半,所以可能有时比微观优化更重要?但是没错,在itertools.groupby中这是一个关键函数。 - Chris_Rands
1
另外,我认为 filter 可能会针对你向其中传递 bool 的情况进行特别优化。 - khelwood
1
@Chris_Rands 我对此的了解基本上仅限于我已经说过的。=)如果它似乎有用,请随意在您的答案中包含任何内容。 - khelwood
2
@khelwood:是的,filterbool 有一个特殊处理,使其等效于传递 None(而不是实际调用回调函数,它直接调用 PyObject_IsTrue)。所以异常情况是 bool 根本没有被调用;如果确实调用了 bool,那么比等效的 truth 更慢。据我所知,唯一另一个识别此情况的函数是 itertools.filterfalse;所有其他 itertools(如 takewhile/dropwhile)都没有提供这样的特殊情况。 - ShadowRanger
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接