0% found this document useful (0 votes)
374 views

Decorator Hand Out

This document provides an overview of Python decorators, including how to define a basic decorator, use decorators with functions and classes, and more advanced topics like parameterized decorators and closures. Key points covered include: how to define a decorator that prints before and after a function is invoked, how *args and **kw allow functions to take arbitrary arguments, how @decorator syntax is syntactic sugar for assigning a decorated function, and how closures can be used to generate functions or decorate functions differently based on parameters.

Uploaded by

rodrigolgol
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
374 views

Decorator Hand Out

This document provides an overview of Python decorators, including how to define a basic decorator, use decorators with functions and classes, and more advanced topics like parameterized decorators and closures. Key points covered include: how to define a decorator that prints before and after a function is invoked, how *args and **kw allow functions to take arbitrary arguments, how @decorator syntax is syntactic sugar for assigning a decorated function, and how closures can be used to generate functions or decorate functions differently based on parameters.

Uploaded by

rodrigolgol
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1

Decorator Template

Python Decorators

>>> import functools


>>> def decorator(func_to_decorate):
...
@functools.wraps(func_to_decorate)
...
def wrapper(*args, **kw):
...
print "before invocation"
...
result = func_to_decorate(*args, **kw)
...
print "after invocation"
...
return result
...
return wrapper

Arguments
Variable arguments and variable keyword arguments are necessary for
functions that accept arbitrary parameters.
*args and **kw
>>>
...
>>>
[2,
>>>
>>>
[3,
>>>
[4,
>>>
[5,
>>>
[6,

def param_func(a, b='b', *args, **kw):


print [x for x in [a, b, args, kw]]
param_func(2, 'c', 'd', 'e,')
'c', ('d', 'e,'), {}]
args = ('f', 'g')
param_func(3, args)
('f', 'g'), (), {}]
param_func(4, *args) # tricksey!
'f', ('g',), {}]
param_func(5, 'x', *args)
'x', ('f', 'g'), {}]
param_func(6, **{'foo':'bar'})
'b', (), {'foo': 'bar'}]

The splat operator (* in a function invocation) is the same as


enumerating the values in the sequence.

Syntactic Sugar

>>> @decorator
... def foo():
...
print "hello"

and:
>>> def foo():
...
print "hello"
>>> foo = decorator(foo)

Invoking a decorated function:


>>> foo()
before invocation
hello
after invocation

>>> param_func(*args) # tricksey!


['f', 'g', (), {}]

and:
Parameterized decorators (need 2 closures)
>>> def limit(length):
...
def decorator(function):
...
@functools.wraps(function)
...
def wrapper(*args, **kw):
...
result = function(*args, **kw)
...
result = result[:length]
...
return result
...
return wrapper
...
return decorator

Closures
Closures are useful as function generators:
>>> def add_x(x):
...
def adder(y):
...
return x + y
...
return adder
>>>
>>>
>>>
15
>>>
17

Closures are also useful for decorators

Decorating classes
>>> class Cat(object):
...
def __init__(self, name):
...
self.name = name
...
...
@decorator
...
def talk(self, txt):
...
print '{0} said, "{1}"'.format(
...
self.name, txt)
...
...
@decorator2
...
def growl(self, txt):
...
print txt.upper()
>>> cat = Cat('Fred')
>>> cat.talk("Meow.")
before invocation
Fred said, "Meow."
after invocation
>>> cat.growl("GRRR.")
before func
GRRR.
after func

More Details
For an in depth explanation of the above check out my ebook, Guide to:
Learning Python Decorators. http://hairysun.com/books/decorators/

>>> @limit(5) # notice parens


... def echo(foo):
...
return foo

and:
>>> def echo(foo):
...
return foo
>>> echo = limit(5)(echo)
>>> echo('123456')
'12345'

Functions can decorate with @limit(1) or @limit(20)...

Python Decorators 1/1

>>> decorator2 = Decorator()


>>> @decorator2
... def nothing(): pass

The following are the same:

add_5 = add_x(5)
add_7 = add_x(7)
add_5(10)
add_7(10)

>>> class Decorator(object):


...
# in __init__ set up state
...
def __call__(self, function):
...
@functools.wraps(function)
...
def wrapper(*args, **kw):
...
print "before func"
...
result = function(*args, **kw)
...
print "after func"
...
return result
...
return wrapper

The following are the same:

The following are equivalent:

>>> param_func(args[0], args[1])


['f', 'g', (), {}]

Class instances as decorators

Matt Harrison 2012


http://hairysun.com/
Note that examples are illustrated as if they were done in a terminal.

You might also like