Introduction to Functional Programming in Python David Jones drj@ravenbrook.com
Python and Functional Programming Beginner Journeyman Master
Programming: Modes of Operation Functional Programming Object Oriented Programming Imperative Programming
FP versus Imperative a spectrum of possibilities ML Python Java more functional more imperative Haskell Scheme Common Lisp C
A Function 5 'foo' in in in double double double out out out 10 'foofoo'
def double(x) : return x * 2 >>> double(5) 10 >>> double('foo') 'foofoo'
First Class Functions Can be... stored in variables; passed as arguments to other functions; returned as results from functions; created at runtime.
def hello() : return 'hello' >>> hello() 'hello' >>> y = hello >>> y() 'hello' >>> type(y) <type 'function'>
Variables refer to Values The hello hello function y
>>> y() 'hello' >>> del hello >>> hello() Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'hello' is not defined >>> help(y) Help on function hello in module __main__: hello()
Factorial def factorial(x) : # Imperative y = 1 for i in range(1,x+1) : y *= i return y def factorial(x) : # Functional if x <= 1 : return 1 else : return x * factorial(x-1)
Lists for a in l : ... map(..., l)
Imperative >>> r=[] >>> for x in range(10) : ... r.append(math.sqrt(x)) ... >>> r [0.0, 1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.2360679774997898, 2.4494897427831779, 2.6457513110645907, 2.8284271247461903, 3.0] Functional >>> map(math.sqrt, range(10)) [0.0, 1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.2360679774997898, 2.4494897427831779, 2.6457513110645907, 2.8284271247461903, 3.0]
� Lambda >>> posts = blog.metaWeblog.getRecentPosts (apiKey, 'drj11', password, 999) >>> len(posts) 59 >>> def postid(p) : return int(p['postid']) ... >>> map(postid, posts) [97, 96, 94, 93, 92, 91, 90, 89, 87, 83, 77, 74, 80, 79, 78, 75, 73, 72, 70, 64, 30, 66, 65, 63, 60, 42, 57, 54, 56, 55, 52, 53, 38, 43, 40, 39, 37, 29, 28, 27, 25, 20, 19, 12, 9, 7, 5, 26, 41, 67, 68, 71, 76, 81, 82, 84, 86, 88, 95] >>> map(lambda p: int(p['postid']), posts)
def fibi(x) : # Imperative s = 0 ; t = 1 for i in range(x) : s,t = t,s+t return s def fibf(x) : # Functional if x <= 1 : return x return fibf(x-1) + fibf(x-2)
Timing def timeit(f) : import time def t(*l) : t0 = time.time() x = f(*l) t1 = time.time() print "Time: %f" % (t1 - t0) return x return t
Timing Fibonacci >>> timefibi = timeit(fibi) >>> timefibf = timeit(fibf) >>> timefibi(30) Time: 0.000026 832040 >>> timefibf(30) Time: 1.042492 832040
Rembering Computations def memo(f) : cache = {} def m(*l) : if not cache.has_key(l) : cache[l] = f(*l) return cache[l] return m
Faster Fibonacci >>> timefibf(30) Time: 1.036864 832040 >>> fibf = memo(fibf) >>> timefibf = timeit(fibf) >>> timefibf(30) Time: 0.000012 832040
Filter >>> filter(lambda x : x % 2 == 0, range(11)) [0, 2, 4, 6, 8, 10] >>> filter(lambda x : x == int(math.sqrt(x))**2, range(40)) [0, 1, 4, 9, 16, 25, 36]
Object Methods and Functions >>> l = ['food', 'python', 'pyfoo'] >>> r = re.compile('fo+') >>> filter(lambda x : r.search(x), l) ['food', 'pyfoo'] >>> filter(r.search, l) ['food', 'pyfoo']
Further Reading
Colophon Slides were prepared using Omnigra � e and Apple's OS X. Python code was generally executed in the CPython implementation version 2.5.1. Presentation was performed using PNG graphics and Apple Preview. The fonts used were Lucida Grande and Monaco, both designed by Bigelow and Holmes. The co � ee bean image is public domain and was created by Mark Sweep. The idea for improving the running time of Fibonacci using memo was suggested by Rici Lake on the Lua mailing list.
Recommend
More recommend