Вы можете использовать next(filter(None, ...))
или next(filter(bool, ...))
, чтобы найти первое истинное значение из списка:
def foo(l):
return next(filter(None, l))
Функция filter()
принимает и функцию фильтра, иитерируемый и возвращает итератор значений из итерируемого, которые проходят фильтр.
Но когда вы устанавливаете функцию фильтра на None
, то это, по сути, то же самое, что и использование bool
в качествефункция фильтра, поэтому разрешены только значения, которые равны true .next()
функция затем дает вам первое такое значение.
Демо:
>>> def foo(l):
... return next(filter(None, l))
...
>>> print(foo([0, None, False, "", [], "hello", None, "bar"]))
hello
Вы можете хотите добавить последнее значениев l
в качестве значения по умолчанию для вызова next()
, если есть только значения Falsey;v1 or v2 or v3 or v4
, по крайней мере, выдаст v4
, если ни одно из значений не является достоверным, поэтому следующее также делает:
def foo(l):
return next(filter(None, l), l[-1])
Использование filter(None, ...)
на дробь быстрее, чем filter(bool, ...)
потому что filter.__next__
реализация тестирует для None
перед тестированием для bool
;эта разница в скорости очень мала и едва измеряется (в пределах погрешности):
>>> import timeit
>>> import random
>>> t = [random.choice([True, False]) for _ in range(10 ** 6)]
>>> for ff in ('bool', 'None'):
... count, total = timeit.Timer(f'deque(filter({ff}, t), maxlen=0)', 'from collections import deque; from __main__ import t').autorange()
... print(f"{ff}: {total / count * 1000:8.4f} ms")
...
bool: 98.9971 ms
None: 95.7907 ms