2

在Python中你可以做

print (0 or None or False or "" or [] or "hello" or None or "bar")

这将打印

hello

你可以对列表做同样的事情吗?即是否有 Python 函数foo以便以下内容也将打印hello

print (foo([0, None, False, "", [], "hello", None, "bar"]))

注意bar不打印。

4

2 回答 2

6

您可以使用next(filter(None, ...))ornext(filter(bool, ...))从列表中找到第一个真值:

def foo(l):
    return next(filter(None, l))

filter()函数同时接受一个过滤器函数和一个迭代器,并返回一个迭代器,该迭代器来自通过过滤器的迭代器中的值。

但是,当您将 filter 函数设置为 时None,它与使用 filter 函数本质上是一样的bool,因此只有true的值才允许通过。然后该next()函数为您提供第一个这样的值。

演示:

>>> def foo(l):
...     return next(filter(None, l))
...
>>> print(foo([0, None, False, "", [], "hello", None, "bar"]))
hello

可能希望添加最后一个值l作为next()调用的默认值,以防只有错误值;v1 or v2 or v3 or v4如果没有一个值是真实的,至少会产生v4,所以以下也是:

def foo(l):
    return next(filter(None, l), l[-1])

使用filter(None, ...)比实现测试快一点,filter(bool, ...)因为它在测试之前测试; 这个速度差异非常小,几乎无法测量(在误差范围内):filter.__next__Nonebool

>>> 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
于 2019-01-30T12:08:06.067 回答
0

您可以将函数reduce()与函数中的运算符or一起使用lambda

from functools import reduce, partial

foo = partial(reduce, lambda x, y: x or y)

print(foo([0, None, False, "", [], "hello", None, "bar"]))
# hello
于 2019-01-30T12:42:44.630 回答