99,9% времени, производительность не имеет значения, поэтому просто используйте bool(my_list)
, как Кит предлагает .
В тех случаях, когда производительность имеет значение , хотя природа bool
означает, что она на самом деле довольно медленная, по крайней мере для эталонного интерпретатора CPython. Он должен проходить через обобщенные пути вызова функций, к обобщенным путям конструктора, к обобщенному разбору аргументов для аргументов 0-1 (и в во всех, кроме самых последних версий Python , проверяя аргументы ключевых слов), все в в конечном итоге просто увеличьте счетчик ссылок на единичный объект и верните его.
Вы можете увидеть, сколько это стоит, с помощью ipython
микробенчмарков (в моей сборке Windows x64 3.6.3):
In [1]: %%timeit -r5 l = []
...: bool(l)
...:
118 ns ± 0.808 ns per loop (mean ± std. dev. of 5 runs, 10000000 loops each)
In [11]: %%timeit -r5 l = [1]
...: bool(l)
...:
117 ns ± 0.306 ns per loop (mean ± std. dev. of 5 runs, 10000000 loops each)
Это может быть неочевидно, но даже на моем относительно слабом ноутбуке 117-118 наносекунд просто для того, чтобы определить правдивость, это немного. К счастью, есть еще пара вариантов. Одним из них является злоупотребление синтаксисом, чтобы пройти выделенный путь для оценки правдивости (начиная с этого момента, я просто протестирую пустой list
, время в основном одинаково в любом случае):
In [3]: %%timeit -r5 l = []
...: not not l
...:
25 ns ± 0.289 ns per loop (mean ± std. dev. of 5 runs, 10000000 loops each)
Это огромное улучшение; это занимает примерно одну пятую времени. В Python 3 использование True if l else False
также работает с равной скоростью, но намного медленнее, чем not not
в Python 2, где True
и False
не являются защищенными литералами, а просто встроенными именами, которые должны загружаться динамически. каждый раз.
Тем не менее, это не идеально; иногда вам нужно вызывать, например, преобразовать множество значений в bool
с помощью функции обратного вызова (например, с map
). К счастью, модуль operator
покрыл operator.truth
; хотя он по-прежнему вызывается со всеми вытекающими издержками, он не является конструктором, он принимает ровно один аргумент (не 0-1) и не допускает аргументы с ключевыми словами, которые все стоят удивительно сумма на ссылочном интерпретаторе CPython. Поэтому, когда вы не можете использовать неявное тестирование на достоверность или преобразование на основе синтаксиса с not not
, и вам все еще нужна скорость, operator.truth
вас охватит:
In [4]: from operator import truth
In [5]: %%timeit -r5 l = []
...: truth(l)
...:
52.1 ns ± 1.1 ns per loop (mean ± std. dev. of 5 runs, 10000000 loops each)
В два раза длиннее not not
, но если вы используете его со встроенными модулями, которые вызывают его многократно (например, map
), с возможностью перенести всю работу на уровень C, полностью избегая выполнения байт-кода, может все же сделать это победой, и это все еще намного дешевле, чем bool()
.
Повторяя мою предыдущую точку зрения: 99,9% времени, производительность не имеет значения , поэтому просто используйте bool(my_list)
, как Кит предлагает . I упомяните об этом только потому, что у меня когда-то был сценарий, в котором это логическое преобразование действительно было самой горячей точкой в моем коде (проверено с помощью профилирования), и использовалось неявное тестирование на достоверность (даже не преобразование, просто возвращая list
с вызывающим if myfunc():
) сократил время выполнения на 30%, а при возврате not not
из list
экономия составила почти 20%.