我无法理解在answer from this site的以下代码中使用or
关键字,该代码显示了使用reduce
对列表进行分区的一种方法:
def partition(l, p):
return reduce(lambda x, y: x[not p(y)].append(y) or x, l, ([], []))
我知道如果条件为真,代码将附加到第一个列表,否则它将附加到第二个列表。 or x
部分的作用是什么?我试着把它排除在外,但最后我发现了TypeError: 'NoneType' object is not subscriptable
答案 0 :(得分:5)
有人打码打高尔夫球。 list.append()
始终返回None
,这是一个假值。通过使用or
,他们可以让lambda
返回第二个表达式的结果; None or ...
始终会返回...
的结果。
您可以使用完整的函数定义替换lambda
:
def func(x, y):
x[not p(y)].append(y)
return x
lambda
和上面的重新定义都返回x
参数,即每次调用中累计值reduce()
。在这种情况下,它是一个元组,有两个列表,其中收集了分区值。
就个人而言,我只是使用了一个循环:
def partition(l, p):
a, b = [], []
for v in l:
target = a if not p(v) else b
target.append(v)
return a, b
毕竟,可读性至关重要。此外,因为它避免了额外的函数调用(输入列表中每个值一次额外调用),所以它也快得多:
>>> import timeit
>>> import random
>>> testdata = [random.randrange(1000) for _ in range(10 ** 4)]
>>> predicate = lambda v: v % 2 == 0
>>> def partition_lambda(l, p):
... return reduce(lambda x, y: x[not p(y)].append(y) or x, l, ([], []))
...
>>> def partition_readable(l, p):
... a, b = [], []
... for v in l:
... target = a if not p(v) else b
... target.append(v)
... return a, b
...
>>> timeit.timeit('part(l, p)', 'from __main__ import partition_lambda as part, testdata as l, predicate as p', number=10**3)
2.5286515180487186
>>> timeit.timeit('part(l, p)', 'from __main__ import partition_readable as part, testdata as l, predicate as p', number=10**3)
1.6824414430302568
因此,对于分区10k项目列表1000次,可读版本只需要reduce()
版本所用时间的2/3。