python decorators decorator(arg)(func) # decorator(arg) must be a decorator st ephane vialette...

25
Python Decorators St´ ephane Vialette LIGM, Universit´ e Paris-Est Marne-la-Vall´ ee October 12, 2009 St´ ephane Vialette (LIGM, Universit´ e Paris-Est Marne-la-Vall´ Python Decorators October 12, 2009 1 / 25

Upload: hoangphuc

Post on 07-Apr-2019

221 views

Category:

Documents


0 download

TRANSCRIPT

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