Fun with funS


Functional programming in Python



Paweł Pamuła

Overview


  • Why do we bother?
  • Is Python a functional language?
  • Does Python have functional features?
  • Let's see how do they work!


Programming paradigms


  • Imperative programming

First do this and next do that

  • Object-oriented programming

Think in terms of objects

  • Functional programming

Evaluate an expression and use the resulting value for something

  • Logic, aspect-oriented, reactive programming...

Functional Concepts


  • First class & higher-order functions
  • Referential transparency (pure functions)

  • Immutable data
  • Lazy evaluation
  • Recursion
  • ...

Advantages of functional approach


  • Describe what you want, not how to get it
  • Concise code
  • Modularity
  • Clarity
  • New perspective!
  • and that is only my opinion :)




Python does not promote functional approach!



I have never considered Python to be heavily influenced by functional languages, no matter what people say or think.

However, earlier on, it was clear that users wanted to do much more with lists and functions.


Functional features in python

  • functions as first-class objects
  • lambdas
  • lazy evaluation
  • map, filter, reduce
  • functools & itertools

First class objects


>>> def forall(fun, val):
... output = []
... for v in val:
... output.append(fun(v))
... return output
...
>>> def double(x):
... return 2*x
...
>>> forall(double, [1, 2, 3, 4])
[2, 4, 6, 8]


LAMBDA FUNCTIONS


  • one-line anonymous functions
  • expression, not a statement
  • single expression, not a block of statements
 >>> reverse = lambda s: s[::-1]
>>> reverse('abc')
'cba'
>>> forall(lambda s: s[::-1], ['abc', 'kajak'])
['cba', 'kajak']

  • strongly connected with map, reduce, filter use

Currying


>>> def log(level, message):
... print "[%s] %s" % (level, message)
...
>>> log("error", "It's gonna explode!")
[error] It's gonna explode!

CURRYING


from functools import partial

def log(level, message):
print "[%s] %s" % (level, message)

levels = ['info', 'warning', 'error', 'debug']
funs = dict((item, partial(log, item)) for item in levels)
funs['info']("That's a very important information")
print funs

[info] That's a very important information

Lazy evaluation


  • Evaluation strategy which delays the evaluation of an expression until its value is needed
  • Enables construction of potentially infinite structures
  • Increases performance


lazy evaluation


  • Python does not use lazy evaluation
  • Even though
>>> 1 or 1/0
1
  • This one takes 3 seconds
>>> import time
>>> print ['some text', time.sleep(3)][0]

  • Most common example: superiority of xrange over range
  • (only in Python 2.#)

MAP


  • Function map takes function and collection as a parameter
  • Applies function to every element


import os
files = ['file1.pdf', 'file2.txt']
filename = lambda f: os.path.splitext(f)[0]
modules = map(filename, files)

['file1', 'file2']

MAP & CURRYING


Sum of integers

 def isum(a, b):
return sum(range(a, b+1))



Sum of squares

def ssum(a, b):
return sum(map(lambda x: x**2, range(a, b+1)))



Sum of roots

 import math def rsum(a, b):
return sum(map(lambda x: math.sqrt(x), range(a, b+1)))

MAP & CURRYING


import math

def general_sum(f):
def inner(a, b):
return sum(map(f, range(a, b+1)))
#returns function!
return inner

log_sum = general_sum(math.log)

print log_sum(1, 10), ' should be more or less equal to ', math.log(reduce(lambda x, y: x*y, range(1, 11)))

 15.1044125731  should be more or less equal to  15.1044125731

REDUCE


  • Retrieves data from the sequence
  • Outputs a single value


  • If sequence s has one element -> returns s[0]
  • If sequence s has two elements -> returns f(s[0], s[1])
  • In case of three elements -> f(f(s[0], s[1]), s[2])
  • And so on...

reduce


 >>> f = lambda a,b: "f(%s,%s)" % (a,b)
>>> reduce(f, '1234')
f(f(f(1,2),3),4)

REDUCE, ANOTHER EXAMPLE


>>> mul = lambda x, y: 10*x + y
>>> reduce(mul, [1, 4, 1, 0])
1410


ANOTHER REDUCE EXAMPLE


 def gcd(a, b):
while b:
a, b = b, a % b
return a

def lcm(a, b):
return a * b // gcd(a, b)

def lcmm(*args):
return reduce(lcm, args)

print lcmm(10, 17, 4)

LAST BUT NOT LEAST: FILTER


  • Accepts function & iterable as an argument
  • Returns (filtered) list
  • Example is superfluous :)

BONUS QUESTION

How are parameters passed to function in Python?

def f(x):
x[0] = 10

def g(x):
x = [4, 5, 6, 7]

def h(some_string):
some_string = 'New string'

x = [0, 1, 2, 3]
f(x)
h(x)

s = 'Some string'
h(s)

Next part of the presentation(?)


  • higher-order functions
  • functools, itertools
  • closures
  • decorators
  • ...



Thank you for your attention!



Paweł Pamuła

pawel.pamula@gmail.com

@github: PawelPamula

Fun with funs

By achr

Fun with funs

Functional aspects of programming in python

  • 228