In [24]:
def addn(n):
def adder(i):
return i + n
return adder
NOTE: you oculd use lambda for something as simple as this...
In [25]:
add2 = addn(2)
In [26]:
add2 (1)
Out[26]:
In [27]:
add3 = addn(3)
In [28]:
add3(1)
Out[28]:
A function that takes a function as an argument, and returns a function can be a decorator.
It usually creates a function inside its scope...
Pass a function as an argument, use that to define the function you return.
(first a couple functions to use...)
In [29]:
def odd(i):
return i%2
def even(i):
return not odd(i)
And write a wrapper for them....
In [30]:
def sieve(f):
def siever(s):
return [x for x in s if f(x)]
return siever
Make a couple of sieves:
In [31]:
oddsieve = sieve(odd)
evensieve = sieve(even)
And try them out:
In [32]:
s = range(10)
s
Out[32]:
In [33]:
oddsieve(s)
Out[33]:
In [34]:
evensieve(s)
Out[34]:
The decorator operator @ abbreviates the preceding pattern
@f
def g
means
g = f(g)
In [35]:
@sieve
def osieve(i):
return i % 2
@sieve
def esieve(i):
return not (i % 2)
In [36]:
osieve(s)
Out[36]:
In [37]:
esieve(s)
Out[37]:
A callable class can be used as a function, so you can also use a class as a decorator
(classes and objects are callable (via __init__
and __call__
))
In [38]:
class Memoize:
"""
memoize decorator from avinash.vora
http://avinashv.net/2008/04/python-decorators-syntactic-sugar/
"""
def __init__(self, function): # runs when memoize class is called
self.function = function
self.memoized = {}
def __call__(self, *args): # runs when memoize instance is called
try:
return self.memoized[args]
except KeyError:
self.memoized[args] = self.function(*args)
return self.memoized[args]
To use it -- the nifty decorator syntax:
In [39]:
@Memoize # same effect as sum2x = memoize(sum2x)
def sum2x(n):
return sum(2 * i for i in xrange(n)) # takes time when n > 10 million
call it:
In [40]:
sum2x(10)
Out[40]:
In [41]:
sum2x(10)
Out[41]:
But slow if you call it with a big number:
In [42]:
import time
start = time.clock()
sum2x(10000000)
print "it took %f seconds to run"%(time.clock() - start)
But the second time...
In [43]:
import time
start = time.clock()
sum2x(10000000)
print "it took %f seconds to run"%(time.clock() - start)
Quiz time: what type of object is sum2x ?
In [44]:
repr(sum2x)
Out[44]:
In [ ]: