I wrote an article like Tips for writing complicated comprehensions in an easy-to-read manner, but I made a library called xcomp based on it. .. Available on Github.
The following are the basic goals.
pip install git+git://github.com/ukyo-su/xcomp@master
comp(collector)
for xcomp import comp
# a = [i for i in range(5)]Instead of
@comp(list)
def a():
for i in range(5):
yield i
# a == [0, 1, 2, 3, 4]
#You can also take the sum. dict and set are also possible
@comp(sum)
def a():
for i in range(5):
yield i
# a == 10
#Easy to read even complicated comprehension
@comp(list)
def fizz_buzz():
for i in range(30):
if i % 15 == 0:
yield "Fizz Buzz"
elif i % 3 == 0:
yield "Fizz"
elif i % 5 == 0:
yield "Buzz"
else:
yield i
multi_comp(*collectors) If you want to create multiple collections in one loop.
from xcomp import multi_comp
data = [(0, 1), (2, 3)]
@multi_comp(list, list)
def a():
for i, j in data:
yield i, j
a_i, a_j = a
# a_i == [0, 2]
# a_j == [1, 3]
reduce_comp(init, for_=None, for_nest=(), result=lambda x: x)
A decorator to write functools.reduce a little easier to read. Racket [for / fold](https://docs.racket-lang.org/reference/for.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._for%2Ffold% 29% 29) is the original story.
from xcomp import reduce_comp
# reduce(lambda sum_, i: sum_ + i, range(5), 0)
@reduce_comp(0, for_=range(5))
def a(sum_, i):
return sum_ + i
# a == 10
#Nested for is also OK
@reduce_comp([], for_nest=(range(3), range(2)))
def a(acc, i, j):
return [*acc, (i, j)]
# a == [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
#When adding one effort at the end
@reduce_comp([], for_=range(5),
result=lambda x: list(reversed(x)))
def a(acc, i):
return [*acc, i]
# a == [4, 3, 2, 1, 0]
# break,also supports continue
@reduce_comp(0, for_=range(100))
def a(acc, i):
if i > 5:
raise BreakReduce
return acc + 1
# a == 6
@reduce_comp(0, for_=range(10))
def a(acc, i):
if i < 5:
raise ContinueReduce
return acc + i
# a == 35
(Is it really easy to read ...?)
multi_reduce_comp(*inits, for_=None, for_nest=(), result=lambda *args: args)
Reduce_comp
when there are multiple variables to accumulate. This is close to Racket's for / fold
.
@multi_reduce_comp(0, [],
for_=range(5))
def a(sum_, rev_list, i):
return sum_ + i, [i, *rev_list]
a_sum, a_rev_list = a
# a_sum == 10
# a_rev_list == [4, 3, 2, 1, 0]
@multi_reduce_comp([], set(),
for_=[0, 1, 1, 2, 3, 4, 4, 4],
result=lambda acc, seen: list(reversed(acc)))
def a(acc, seen, i):
if i in seen:
return acc, seen
else:
return [i, *acc], {*seen, i}
# a == [0, 1, 2, 3, 4]
delay_arg(func, *args, **kwargs)
A higher-order function for turning the first argument to the end. delay_arg (f, * args, ** kwargs) (a)
becomes f (a, * args, ** kwargs)
.
You can use map
, filter
, reduce
as decorators.
@list
@delay_arg(map, range(5))
def a(i):
return i * 2
# a == [0, 2, 4, 6, 8]
Recommended Posts