Home > AI > Language > Python >

decorator

Definition: allow the user the add new functionality to the existent object without changing its structure.

Example 1: create a basic decorator

def decorator(f):

    # modify the f
    def wrapper():
        result = f()  # string
        upper_result = result.upper()
        return upper_result

    return wrapper
    
    
    
@decorator
def say_hi():
    return 'hello there'

a = say_hi()
b = decorator(say_hi)() # function as the input variable
print(a)
print(b)

Example 2:
decorator without paramter
function variable with parameter

def prepost(f):

    def wrapper(*args, **kwargs):
        print(" start")
        result = f(*args, **kwargs)
        print(" end")
        return result

    return wrapper


@prepost
def multiplication(x, y):
    print('middle')
    return x * y

print(multiplication(3, 4))

Example 3:
decorator with parameter;
function variable without parameter

def decorator(*dargs, **dkwargs):
    print("Step 1")
      
    def wrapper(f): # function variable is here
        print("Step 3")
        print("I like", dkwargs['like'])
        result = f()
        return result
        
    print("Step 2")
    
    return wrapper
  
  
@decorator(like = "geeksforgeeks")
def my_func():
    print("Step 4")

Example 4:
decorator with parameters
function variable with parameters

def decorator(*dargs, **dkwargs):
    print("Step 1")

    def inner(f):
        print("Step 3")

        def wrapper(*fargs, **fkwargs):
            print("Step 5")
            print("sum of decorator paramters {}".format(dkwargs['x']+dkwargs['y']) )
            result = f(*fargs, **fkwargs)
            return result

        print("Step 4")
        return wrapper

    print("Step 2")

    return inner


@decorator(x=1, y=2)
def my_fun(*args):
    print("Step 6")
    for ele in args:
        print(ele)

# another way of using dacorators
my_fun('a', 'b', 'c')

Example 5:
multiple decorators without parameters
implemented by functools

from functools import wraps

def makebold(fn):
    @wraps(fn)
    def wrapped(*args, **kwargs):
        return "<b>" + fn(*args, **kwargs) + "</b>"
    return wrapped

def makeitalic(fn):
    @wraps(fn)
    def wrapped(*args, **kwargs):
        return "<i>" + fn(*args, **kwargs) + "</i>"
    return wrapped

@makebold
@makeitalic
def hello():
    return "hello world"

@makebold
@makeitalic
def log(s):
    return s

print(hello())        # returns "<b><i>hello world</i></b>"
print(hello.__name__) # with functools.wraps() this returns "hello"
print(log('hello'))  # returns "<b><i>hello</i></b>"

Example 6: decorator with optional parameters (both decorators need parenthesis)

from functools import wraps

def decorator(colour=None):

    def inner(func):
        colour_open = ('<span style="color: {};">'.format(colour)
                       if colour else '')
        colour_close = '</span>' if colour else ''
        
        
        def wrapper(*args, **kwargs):
            return ('{colour_open}<b>{message}</b>{colour_close}'
                    .format(colour_open=colour_open,
                            colour_close=colour_close,
                            message=func(*args, **kwargs)))
        return wrapper
        
    return inner





@decorator()
def say_hello(user):
    return 'hello, {}'.format(user)

@decorator(colour='red')
def say_bye(user):
    return 'See you, {}'.format(user)
    
    
print(say_hello("good"))
print(say_bye("good"))

Example 7: decorator with and without parenthesis



# func != None: @decorator
# func = None: @decorator()
def decorator(func=None, prefix=None):

    def inner(f):
        def wrapper(*a, **ka):
            if prefix:
                print(f"{prefix} start")
            result = f(*a, **ka)
            if prefix:
                print(f"{prefix} end")
        return wrapper


    if callable(func):
        return inner(func) # 2 levels
    else:
        return inner # 3 levels



@decorator(prefix="outer")
def say_good():
    print("bye")
    
@decorator()
def say_hi():
    print("hello")
    
@decorator
def say_bye():
    print("bye")
    
    
say_good()
say_hi()
say_bye()

Leave a Reply