Python Decorators decorator(arg)(func) # decorator(arg) must be a decorator St ephane Vialette...
Transcript of Python Decorators decorator(arg)(func) # decorator(arg) must be a decorator St ephane Vialette...
PythonDecorators
Stephane Vialette
LIGM, Universite Paris-Est Marne-la-Vallee
October 12, 2009
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 1 / 25
Outline
1 Introduction
2 Decorators without arguments
3 Decorators without arguments
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 2 / 25
Introduction
Outline
1 Introduction
2 Decorators without arguments
3 Decorators without arguments
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 3 / 25
Introduction
Decorators
Description
Decorators are just overlays on top of function calls.These overlaysare jsut additional call that are applied when a function or method isdeclared.
The syntax for decorators uses a leading at-sign (@) followed by thedecorator name and optional arguments.
Syntaxe
func = decorator1(decorator2(decorator3(func(arg1, arg2, ...))))
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 4 / 25
Introduction
Stacking
Description
Stacking multiple decorators
@decorator1@decorator2@decorator3def func (arg1, arg2, ...):
pass
is equivalent to creating acomposite function
func = decorator1(decorator2(decorator3(func(arg1, arg2, ...))))
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 5 / 25
Decorators without arguments
Outline
1 Introduction
2 Decorators without arguments
3 Decorators without arguments
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 6 / 25
Decorators without arguments
Decorators without arguments
Example
def entry exit(f):def wrapped():
print ">> Entering", f. name , ’>>’ ,f()print "<< Exited", f. name , ’<<’
return wrapped
@entry exitdef func():
print "Inside func",
@entry exitdef func2():
print "inside func2",
if name == ’ main ’:func() # >> Entering func >> Inside func << Exited func <<func2() # >> Entering func2 >> inside func2 << Exited func2 <<
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 7 / 25
Decorators without arguments
Measuring the running time
Example
import time
def timeit(func):def timed(*args, **kw):
ts = time.time()result = func(*args, **kw)te = time.time()print ’%r (%r, %r) %2.2f sec’ % (func. name , args, kw, te-ts)return result
return timed
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 8 / 25
Decorators without arguments
Measuring the running time
Example
import timefrom timeit import timeit
class C(object):@timeitdef f(self):
time.sleep(0.2)
@timeitdef g():
time.sleep(1)
c = C()c.f() #’f’ ((< main .C object at 0xb7e2df4c>,), {}) 0.20 secg() # ’g’ ((), {}) 1.00 sec
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 9 / 25
Decorators without arguments
Check that the supplied argument is an integer
Example
def requireint(func):def wrapper (arg):
assert isinstance(arg, int)return func(arg)
return wrapper
@require intdef g(arg):
...
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 10 / 25
Decorators without arguments
Decorators as classes
Description
The only constraint upon the object returned by the decorator is thatit can be used as a function – which basically means it must becallable.
Thus, any classes we use as decorators must implement call .
class MyDecorator(object):def init (self, func):
# do something with func ...def call (*args):
# do something args
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 11 / 25
Decorators without arguments
Classes as decorators
Fibonacci
In [1]: class Decorator(object):...: def init (self, func):...: print ’Decorator. init ’
...: self. func = func
...: def call (self, *args):
...: print ’Decorator. call ’
...: return self. func(args)In [2]: @Decorator
...: def f(arg):
...: print ’f(%s)’ % (arg,)Decorator. initIn [3]: DecoratorOut[3]: <class ’ main .Decorator’>In [4]: fOut[4]: < main .Decorator object at 0x913f12c>In [5]: f(’arg’)Decorator. callf((’arg’,))
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 12 / 25
Decorators without arguments
Memoized
Fibonacci
def fibonacci(n):print ’fibonacci(%d)’ % n,if 0 <= n <= 1:
return nelse:
return fibonacci(n-1) + fibonacci(n-2)
fibonacci(5)
Output
fibonacci(5) fibonacci(4) fibonacci(3) fibonacci(2) fibonacci(1) fibonacci(0) fibonacci(1)fibonacci(2) fibonacci(1) fibonacci(0) fibonacci(3) fibonacci(2) fibonacci(1) fibonacci(0)fibonacci(1)
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 13 / 25
Decorators without arguments
Memoized
Fibonacci
class Memoized(object):def init (self, func):
print ’Memoized. init ’self. func = funcself. cache = {}
def call (self, *args):print ’Memoized. call ’,try:
return self. cache[args]except KeyError:
self. cache[args] = value = self. func(*args)return value
except TypeError:return self. func(*args)
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 14 / 25
Decorators without arguments
Memoized
Fibonaccifrom memoized import Memoized@Memoizeddef fibonacci(n):
print ’fibonacci(%d)’ % n,if 0 <= n <= 1:
return nelse:
return fibonacci(n-1) + fibonacci(n-2)
fibonacci(5)
Output
Memoized. initMemoized. call fibonacci(5) Memoized. call fibonacci(4) Memoized. call fibonacci(3)Memoized. call fibonacci(2) Memoized. call fibonacci(1) Memoized. call fibonacci(0)Memoized. call Memoized. call Memoized. call
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 15 / 25
Decorators without arguments
Counting function calls
Example
class countcalls(object):
def init (self, func):self. func = funcself. numcalls = 0
def call (self, *args, **kwargs):self. numcalls += 1return self. func(*args, **kwargs)
def count(self):return self. numcalls
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 16 / 25
Decorators without arguments
Counting function calls
Example
@countcallsdef f1():
pass
@countcallsdef f2():
pass
print ’f1:’, f1print ’f2:’, f2
for in range(3):f1()
for in range(2):f1()f2()
print f1.count() # would print 5print f2.count() # would print 2
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 17 / 25
Decorators without arguments
Counting function calls
This does not work !
class countcalls(object):instances = {}
def init (self, func):self. func = funcself. numcalls = 0countcalls. instances[func] = self
def call (self, *args, **kwargs):self. numcalls += 1return self. func(*args, **kwargs)
@staticmethoddef count(func):
return countcalls. instances[func]. numcalls
@staticmethoddef counts():
return dict([(func, countcalls.count(func)) for func in countcalls. instances])
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 18 / 25
Decorators without arguments
Outline
1 Introduction
2 Decorators without arguments
3 Decorators without arguments
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 19 / 25
Decorators without arguments
Decorators with arguments
Description
Decorators can have arguments, like in
@decorator(arg)def func():
...
is equivalent to creating acomposite function
func = decorator(arg)(func) # decorator(arg) must be a decorator
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 20 / 25
Decorators without arguments
Adding an attribute
Example
In [1]: def option(value):...: def decorator(func):...: func.attribute = value...: return func...: return decorator...:
In [2]: @option(’a value’)...: def f():...: pass...:
In [3]: f()In [4]: f.attributeOut[4]: ’a value’
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 21 / 25
Decorators without arguments
Checking type
Example
def return bool(bool value):def wrapper(func):
def wrapped(*args):result = func(*args)if result != bool:
raise TypeErrorreturn result
return wrappedreturn wrapper
@return bool(True)def always true():
return Truealways true() # ok
@return bool(False)def always false():
return Truealways false() # raise TypeError
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 22 / 25
Decorators without arguments
Easy adding methods to a class instance 1/3
Example
In [1]: import new
In [2]: new.instancemethod?Type: typeBase Class: <type ’type’>String Form: <type ’instancemethod’>Namespace: InteractiveDocstring:
instancemethod(function, instance, class)
Create an instance method object.
In [3]:
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 23 / 25
Decorators without arguments
Easy adding methods to a class instance 2/3
Example
# Add a new method to a class instance.# Credits to John Roth.def addto(instance):
def decorator(func):import newfunc = new.instancemethod(func, instance, instance. class )setattr(instance, func.func name, func)return func
return decorator
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 24 / 25
Decorators without arguments
Easy adding methods to a class instance 3/3
Example
class C(object):def init (self, val):
self.attribute = val
c1 = C(123)c2 = C(456)
@addto(c1)def print attribute(self):
print self.attribute
c1.print attribute() # would print 123c2.print attribute() # AttributeError: ’C’ object has no attribute ’print attribute’
Stephane Vialette (LIGM, Universite Paris-Est Marne-la-Vallee)Python Decorators October 12, 2009 25 / 25