# Functional Programming¶

## Variable arguments and Keyword arguments¶

In [3]:
max(1, 2, 3, 4)

Out[3]:
4
In [4]:
dict(a=1, b=2)

Out[4]:
{'a': 1, 'b': 2}
In [5]:
def add(*args):
return sum(args)


10

In [6]:
def mydict(**kwargs):
return kwargs

print mydict(a=1, b=2)

{'a': 1, 'b': 2}

In [10]:
def render_tag(tagname, **attrs):
pairs = ["%s=%s" % (k,v) for k, v in attrs.items()]
return "<%s %s/>" % (tagname, " ".join(pairs))

render_tag("input", type="text", name="x", id="x")

Out[10]:
'<input type=text name=x id=x/>'
In [11]:
numbers = [1, 2, 3, 4]

10


Problem: Write a function call_func(f, *args, **kwargs), that calls the given function f with args and kwargs.

def square(x):
return x*x
print call_func(square, 2)
print call_func(square, x=2)

return a + b

print call_func(max, 2, 3, 4, 5, 6, 7)
print call_func(dict, a=1, b=2, c=3)
In [14]:
def add(a, b): return a+b
args=[1]
kwargs={"b": 2}


3

In [15]:
def call_fun(f, *args, **kwargs):
return f(*args, **kwargs)


## Back to Decorators¶

In [21]:
import time
def timeit(f):
def g():
t0 = time.time()
value = f()
t1 = time.time()
print "took %f seconds" % (t1-t0)
return value
return g

def timepass():
for i in range(10000):
for j in range(1000):
x = i*j
return 0

def timepass2(n):
for i in range(n):
for j in range(1000):
x = i*j
return 0

timepass = timeit(timepass)
print timepass()

import urllib
@timeit
def wget(url):

x = wget("http://python.org")

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-868cc2b3e2d9> in <module>()
31
---> 32 x = wget("http://python.org")

TypeError: g() takes no arguments (1 given)
took 0.772692 seconds
0


Problem: Write a decorator vectorize, that takes a function working on single value and make it work on a list.

@vectorize
def square(x):
return x*x

print square([1, 2, 3, 4]) # should print [1, 4, 9, 16]

### Example: Web Framework¶

In [6]:
%%file bicycle.py
mapping = []
before_hooks = []

def request(url):
for path, func in mapping:
if path == url:
for h in before_hooks:
h(url)
return func()

def route(path):
def decorator(f):
mapping.append((path, f))
return f
return decorator

def before_request(f):
before_hooks.append(f)
return f

Overwriting bicycle.py

In [8]:
from bicycle import route, request, before_request
import time

@route("/hello")
def hello():
return "Hello, world"

@route("/bye")
def bye():
return "Goodbye"

@before_request
def log(url):
print time.asctime(), url

if __name__ == "__main__":
print "MAIN"
print request("/hello") # should print "Hello, world"
print request("/bye")
print request("/foo")

MAIN
Sat May 25 10:53:05 2013 /hello
Hello, world
Sat May 25 10:53:05 2013 /bye
Goodbye


### Example: writing command line apps using decorators¶

In [44]:
%%file command0.py
def command(f):
def g(filenames, **kw):
#lines = (outline for line in lines
#                 for outline in f(line, **kw))
lines = generate_output(f, lines, **kwargs)
printlines(lines)
return g

def generate_output(f, lines, **kwargs):
for line in lines:
for outline in f(line, **kwargs):
yield outline

for f in filenames:
for line in open(f):
yield line

def printlines(lines):
for line in lines:
print line.strip("\n")

Overwriting command0.py

In [36]:
%%file uppercase.py
from command0 import command

@command
def uppercase(line):
yield line.upper()

if __name__ == "__main__":
import sys
uppercase(sys.argv[1:])

Overwriting uppercase.py

In [37]:
!python uppercase.py uppercase.py

FROM COMMAND0 IMPORT COMMAND

@COMMAND
DEF UPPERCASE(LINE):
YIELD LINE.UPPER()

IF __NAME__ == "__MAIN__":
IMPORT SYS
UPPERCASE(SYS.ARGV[1:])

In [38]:
%%file grep.py
from command0 import command

@command
def grep(line, pattern):
if pattern in line:
yield line

if __name__ == "__main__":
import sys
pattern = sys.argv[1]
filenames = sys.argv[2:]
grep(filenames, pattern=pattern)

Overwriting grep.py

In [39]:
!python grep.py def grep.py

def grep(line, pattern):

In [42]:
%%file twice.py
from command0 import command

@command
def twice(line):
yield line
yield line

if __name__ == "__main__":
import sys
twice(sys.argv[1:])

Overwriting twice.py

In [43]:
!python twice.py twice.py

from command0 import command
from command0 import command

@command
@command
def twice(line):
def twice(line):
yield line
yield line
yield line
yield line

if __name__ == "__main__":
if __name__ == "__main__":
import sys
import sys
twice(sys.argv[1:])
twice(sys.argv[1:])


### exec and eval¶

In [45]:
code = "x = 1"
exec(code)
print x

1

In [46]:
eval("1 + 2")

Out[46]:
3
In [47]:
env = {"x": 2}
eval("x + 2", env)

Out[47]:
4