Reputation: 427
I can't understand the use of the or
keyword in the following code taken from an answer from this site that showed one way to partition a list using reduce
:
def partition(l, p):
return reduce(lambda x, y: x[not p(y)].append(y) or x, l, ([], []))
I understand that the code will append to the first list if the condition is true, otherwise it appends to the second. What does the part or x
do? I tried leaving that out but I ended up with an error saying TypeError: 'NoneType' object is not subscriptable
Upvotes: 2
Views: 51
Reputation: 1122382
Someone is code golfing. list.append()
always returns None
, which is a false value. By using or
they can then have the lambda
return the result of a second expression; None or ...
always returns the result of ...
.
You could replace the lambda
with a full function definition:
def func(x, y):
x[not p(y)].append(y)
return x
Both the lambda
and the above re-definition return the x
argument, which is the cumulative value reduce()
passes in each call. In this case it is a tuple with two lists into which the partitioned values are collected.
Personally, I'd just have used a loop:
def partition(l, p):
a, b = [], []
for v in l:
target = a if not p(v) else b
target.append(v)
return a, b
Readability matters, after all. Moreover, because it avoids additional function calls (one extra call per value in the input list), it is also quite a bit faster:
>>> 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
So for partitioning a 10k item list, 1000 times, the readable version takes only 2/3rds of the time that the reduce()
version takes.
Upvotes: 5