# CONDITIONAL EXPRESSIONS # expr1 IF cond ELSE expr2 5 if x%2 == 0 else 6 # COMPREHENSION EXPRESSIONS # List comprehensions # [ expr for x in xs if cond ] [x**2 for x in [1,2,3,4,5]] [x+y for x in [1,2,3] for y in range(x) if x+y>3] # Set comprehensions # { expr for x in xs if cond } {x+y for x in [1,2,3] for y in [1,2]} {x+y for (x,y) in zip([1,2],[5,4])} # Dictionary comprehensions # { keyexpr:valexpr for x in xs if cond } {x:"a"*(x**2) for x in [1,2,3]} {n:p for (n,p) in zip(['Jon','Ali'], ['111','222'])} # PURE FUNCTIONS AND LAMBDA EXPRESSIONS # A function is pure if it returns the same answer on the same # input at all times and all places # Lambda Expressions # lambda plist: expr lambda x,y: math.sqrt(x**2+y**2) (lambda x,y: math.sqrt(x**2+y**2))(3,4) f = lambda x,y: math.sqrt(x**2+y**2) f(3,4) # MAP, FILTER, REDUCE # map(f,xs) list(map(lambda x: 2*x, [1,2,3,4,5])) # filter(f,xs) list(filter(lambda x: x%2==0, [1,2,3,4,5,6,7])) # reduce(f,xs,acc) from functools import reduce reduce(lambda acc,x: acc+x,[1,2,3],0) # IMMUTABLE OBJECTS AND BUILT-IN FUNCTIONS # Python Strings and Tuples >>> xs = [1,5,3,2] >>> ys = sorted(xs) >>> print(xs,ys) [1, 5, 3, 2] [1, 2, 3, 5] >>> d = {"a":20, "b":12, "c": 98} >>> list(d.keys()) ['a', 'b', 'c'] >>> list(d.items()) [('a', 20), ('b', 12), ('c', 98)] >>> list(zip([1,2,3],['a','b','c'])) [(1, 'a'), (2, 'b'), (3, 'c')] >>> ",".join(["a","b"]) 'a,b' # PURE FUNCTIONAL PROGRAMMING IN PYTHON May use - conditional expressions, - list/set/dictionary comprehensions, - lambdas, - map, filter, reduce, and - other useful functions/methods that do not mutate their inputs. May not use - any kind of loop-, - if-, if-else-, if-elif-else- Typically, the solution should contain sequence of assignment statements, where the variables on the left-hand side of the assignment is used only to name an expression. Decomposing the solution into functions is fine as long as the code within the function also follows the restrictions. Many of the local looping code can be accomplished using the collection comprehensions. Others can be accomplished by recursive functions. EXAMPLE Consider the problem of finding ``twin'' primes less than a given number, where a twin prime is a pair of primes that differ by 2. def removeMultiples(x,xs): return [] if xs == [] else removeMultiples(x,xs[1:]) if xs[0]%x == 0 else [xs[0]] + removeMultiples(x,xs[1:]) def sieve(xs): return [] if xs == [] else [xs[0]] + sieve( removeMultiples(xs[0],xs[1:])) def filterTwins(pairs): return [pair for pair in pairs if pair[0]+2 == pair[1]] def twinPrimes(n): ps = sieve([x for x in range(2,n+1)]) return filterTwins(list(zip(ps,ps[1:]))) # PROGRAMMING WITH (ONLY) EXPRESSIONS Y = (lambda f: (lambda g: f(lambda n: g(g)(n))) (lambda g: f(lambda n: g(g)(n))) ) rmMul = lambda f: lambda x: lambda xs: [] if xs == [] else f(x)(xs[1:]) if xs[0]%x == 0 else [xs[0]] + f(x)(xs[1:]) removeMultiples = ((lambda f: (lambda g: f(lambda n: g(g)(n))) (lambda g: f(lambda n: g(g)(n))) ))(lambda f: lambda x: lambda xs: [] if xs == [] else f(x)(xs[1:]) if xs[0]%x == 0 else [xs[0]] + f(x)(xs[1:])) removeMultiples(2)([2,3,4,5,6,7,8])