This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: bool() vs len() > 0 on lists
Type: performance Stage: resolved
Components: Versions: Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: dilyan.palauzov, rhettinger, serhiy.storchaka
Priority: normal Keywords:

Created on 2017-11-30 11:31 by dilyan.palauzov, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (8)
msg307294 - (view) Author: Дилян Палаузов (dilyan.palauzov) Date: 2017-11-30 11:31
Please make bool() on lists at least as fast as len() > 0 on lists is.

The trivial approach would be to define __bool__ on lists, that do something like  "True if self else False".

python3 
Python 3.6.3+ (heads/3.6-dirty:2b5cbbb13c, Nov  1 2017, 19:03:09) 
[GCC 6.4.1 20171025] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> timeit.timeit('len([]) > 0')
0.0983404889702797
>>> timeit.timeit('bool([])')
0.15502946823835373
>>> timeit.timeit('True if [] else False')
0.03108721226453781
>>> timeit.timeit('len([1]) > 0')
0.11656427383422852
>>> timeit.timeit('bool([1])')
0.19317257404327393
>>> timeit.timeit('True if [1] else False')
0.057590410113334656
msg307300 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-11-30 12:10
The cause of len() been faster than bool() is the same as why repr() is faster than str(). [1] len() and repr() are functions that just call corresponding slots, while bool() and str() are constructors.

In most cases you shouldn't use `bool(obj)` or `len(obj) > 0`. Instead use just `obj` in conditions.

If you can provide a patch that speeds up constructions of simple class instances, please open a pull request on GitHub. Otherwise this issue will be closed.

[1] https://stackoverflow.com/questions/45376719/why-is-reprint-faster-than-strint
msg307306 - (view) Author: Дилян Палаузов (dilyan.palauzov) Date: 2017-11-30 13:28
To my understanding this optimization (bool([]) faster than len([])) cannot be made until PyObject_Bool is introduced, similar to PyObject_Repr and PyObject_Length.

Am I not going to provide a patch.
msg307309 - (view) Author: Дилян Палаузов (dilyan.palauzov) Date: 2017-11-30 13:39
Under these circumstances https://wiki.python.org/moin/PythonSpeed/PerformanceTips shall be updated to state that 

"len('a list') > 0" is slower than "True if 'a list' else False"
msg307311 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-11-30 13:45
I don't know what should mean PyObject_Bool(), but in C code you should use PyObject_IsTrue() for getting the boolean value of the object.
msg307313 - (view) Author: Дилян Палаузов (dilyan.palauzov) Date: 2017-11-30 14:07
Is the speedup a matter of adding "__bool__" to list_methods in object/listobject.c?

In any case, I am not in the internals of cpython, so that I am not going to provide a patch.

With PyObject_Bool I meant PyObject_IsTrue.
msg307405 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-12-01 19:45
ISTM that there isn't a real issue here and the discussions of proper timing technique and micro-optimizations are more suitable for StackOverflow.
msg307408 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-12-01 20:00
I'm sure adding list.__bool__() will not affect the performance. The real source of the difference is explained on the StackOverflow link.

PEP 8 contains a rule for testing the emptiness of a container.
History
Date User Action Args
2022-04-11 14:58:55adminsetgithub: 76361
2017-12-01 20:00:08serhiy.storchakasetstatus: open -> closed
resolution: not a bug
messages: + msg307408

stage: resolved
2017-12-01 19:45:56rhettingersetnosy: + rhettinger
messages: + msg307405
2017-11-30 14:07:00dilyan.palauzovsetmessages: + msg307313
2017-11-30 13:45:08serhiy.storchakasetmessages: + msg307311
2017-11-30 13:39:06dilyan.palauzovsetmessages: + msg307309
2017-11-30 13:28:31dilyan.palauzovsetstatus: pending -> open

messages: + msg307306
2017-11-30 12:10:17serhiy.storchakasetstatus: open -> pending
versions: + Python 3.7, - Python 3.6
nosy: + serhiy.storchaka

messages: + msg307300
2017-11-30 11:31:47dilyan.palauzovcreate