以下代码中使用'或'关键字有什么用?

时间:2017-12-11 16:59:37

标签: python reduce

我无法理解在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

的错误

1 个答案:

答案 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。