11  Decorator

from functools import wraps

11.1 Concept

def outer_func(msg):
    def inner_func():
        print(msg)
    return inner_func

Traditional function factory

my_func_1 = outer_func("hi")
my_func_2 = outer_func("bro")

my_func_1()
my_func_2()
hi
bro

11.2 Basic Usage

def your_decorator(func):
  def wrapper():
    # Do stuff before func...
    print("Before func!")
    func()
    # Do stuff after func...
    print("After func!")
  return wrapper

11.2.1 Decorator

@your_decorator
def foo():
  print("Hello World!")

foo()
Before func!
Hello World!
After func!
del foo # Clean up

11.2.2 Manually

def foo():
  print("Hello World!")
foo_dec = your_decorator(foo)
foo_dec()
Before func!
Hello World!
After func!

11.3 Decorator with Parameters

def your_decorator(func):
  def wrapper(*args,**kwargs):
    # Do stuff before func...
    print("Before func!") 
    func(*args,**kwargs)
    # Do stuff after func...
    print("After func!")
  return wrapper

@your_decorator
def foo(bar):
  print("My name is " + bar)

foo("Jack")
Before func!
My name is Jack
After func!

11.4 Decorator Template

import functools

def your_decorator(func):
  @functools.wraps(func) # For preserving the metadata of func.
  def wrapper(*args,**kwargs):
    # Do stuff before func...
    result = func(*args,**kwargs)
    # Do stuff after func..
    return result
  return wrapper