bool значение списка в Python - PullRequest
7 голосов
/ 24 марта 2012

Каков наилучший способ превратить список в значение bool? Я ищу что-то вроде:

return eval_bool(my_list)

У меня есть специальный контейнер, в котором я реализую метод __nonzero__, который должен работать следующим образом:

if self.my_list:
    return True
return False

Но достаточно ли это питона? :) В любом случае, мне любопытно, как Python интерпретирует значение списка в операторе if, потому что этот код работает по-другому:

return my_list == True

J.

Ответы [ 4 ]

19 голосов
/ 24 марта 2012

Просто используйте:

bool(my_list)

Что оценивает его как истинность Python и возвращает реальное логическое значение.

1 голос
/ 05 октября 2018

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%.

1 голос
/ 24 марта 2012

Если len(my_list) == 0, то возвращается как false, в противном случае это true.Пиктонично писать:

return len(my_list)

, которое, хотя и возвращается как целое число, оценивается как true для ненулевой длины, в противном случае - false.

0 голосов
/ 05 октября 2018

Вы можете использовать троичный оператор "если".Google говорит, что поддерживается с 2.5

foo = True if your_list else False
...