In [1]:
def addn(n):
def adder(i):
return i + n
return adder
NOTE: you oculd use lambda for something as simple as this...
In [2]:
add2 = addn(2)
In [3]:
add2 (1)
Out[3]:
In [4]:
add3 = addn(3)
In [5]:
add3(1)
Out[5]:
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 [6]:
def odd(i):
return i%2
def even(i):
return not odd(i)
And write a wrapper for them....
In [8]:
def sieve(f):
def siever(s):
return [x for x in s if f(x)]
return siever
Make a couple of sieves:
In [9]:
oddsieve = sieve(odd)
evensieve = sieve(even)
And try them out:
In [10]:
s = range(10)
s
Out[10]:
In [11]:
oddsieve(s)
Out[11]:
In [12]:
evensieve(s)
Out[12]:
The decorator operator @ abbreviates the preceding pattern
@f
def g
means
g = f(g)
In [13]:
@sieve
def osieve(i):
return i % 2
@sieve
def esieve(i):
return not (i % 2)
In [16]:
osieve(s)
Out[16]:
In [17]:
esieve(s)
Out[17]:
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 [18]:
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 [19]:
@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 [20]:
sum2x(10)
Out[20]:
In [21]:
sum2x(10)
Out[21]:
But slow if you call it with a big number:
In [22]:
import time
start = time.clock()
sum2x(10000000)
print "it took %f seconds to run"%(time.clock() - start)
But the second time...
In [23]:
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 [24]:
repr(sum2x)
Out[24]:
In [ ]: