Map, Reduce, Filter are paradigms of functional programming. WIth them, we can write simpler and shorter programs. They are applied on iterables.
Map
map(callable, iterable) applies callable to every iterable.
Example: Add 1 to each element in the list.
1
2
# Unpack map obj (applies the function on everything in the list)
x,y,z=map(lambdax:x+1,[1,2,3])
Reduce
reduce(callable, iterable) can apply callable on iterable, accumulatively, meaning in the below example, the lambda is applied on each item and the current accumulated result.
1
2
3
4
5
fromfunctoolsimportreducels=[1,2,3,4,5]# see 18, the sum of ls
print(reduce(lambdax,y:x+y,ls))
max, min, sorted takes in a function returns a “key” for sorting
1
2
3
ls=["str1","str222","str3333"]max(ls,key=lambdax:len(x))# see "str3333"
Filter
Filter, as its name suggests, returns a filter(predicate, iterable) objects that can be casted into a “leaned down” iteration, after applying predicate.
1
2
3
4
di={1:"1",2:"2",3:"3"}# converts to [(1, "1"), (2, "2"), (3, "3")]
di_list=list(di.items())print(list(filter(lambdax:x[0]<3,di_list)))
Lambda Function
A lambda expression is a function without name.
1
2
3
#input is x, return x+1
b=lambdax:x+1printb(1)
Functools
partial
functools.partial returns a wrapper with some args bound to given values.
1
2
3
4
5
6
7
8
# 1 partial - we just need to bind the function with any keyworded args
fromfunctoolsimportpartialdeffunc(a,b):print("func: ",a,b)func_w=partial(func,b=12)func_w(a=13)
Its equivalent implementation is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
defrico_partial(func,*args,**kwargs):# simplified version
# def wrapper(a):
# # kwargs here is a dict, need to unpack it
# return func(a, **kwargs)
# return wrapper
defwrapper(*extra_args,**extra_kwargs):# need nonlocal since we are reusing args, and kwargs, which will be true local vars
nonlocalargs,kwargs# args here is a tuple already
args=list(args)args.extend(extra_args)kwargs={**kwargs,**extra_kwargs}returnfunc(*args,**kwargs)returnwrapperrico_func_w=rico_partial(func,b=12)rico_func_w(a=13)
cached, lru_cache
lru_cache caches the result of up to a maximum number of recent calls. Once there are more functions than the max, the least called functions are discarded.
It came with Python 3.2
1
2
3
4
5
6
7
8
9
10
fromfunctoolsimportlru_cache@lru_cache(maxsize=128)defexpensive_function(x):print(f"Computing for {x}")returnx*2print(expensive_function(2))# Computes and caches the result
print(expensive_function(2))# Returns cached result
cache came with Python 3.9. It simply caches results of all functions. It’s equivalent to lru_cache(maxsize=None)
1
2
3
4
5
6
7
8
9
fromfunctoolsimportcache# Python 3.9+
@cachedefexpensive_function(x):print(f"Computing for {x}")returnx*2print(expensive_function(2))# Computes and caches the result
print(expensive_function(2))# Returns cached result