Python decorator? - can someone please explain this?

Viewed 18103

Apologies this is a very broad question.

The code below is a fragment of something found on the web. The key thing I am interested in is the line beginning @protected - I am wondering what this does and how it does it? It appears to be checking that a valid user is logged in prior to executing the do_upload_ajax function. That looks like a really effective way to do user authentication. I don't understand the mechanics of this @ function though - can someone steer me in the right direction to explain how this would be implemented in the real world? Python 3 answers please. thanks.

@bottle.route('/ajaxupload', method='POST')
@protected(check_valid_user) 
def do_upload_ajax():
    data = bottle.request.files.get('data')
    if data.file:
        size = 0
6 Answers

A decorator is a function that takes a function as its only parameter and returns a function. This is helpful to “wrap” functionality with the same code over and over again.

We use @func_name to specify a decorator to be applied on another function.

Following example adds a welcome message to the string returned by fun(). Takes fun() as parameter and returns welcome().

def decorate_message(fun):

    # Nested function
    def addWelcome(site_name):
        return "Welcome to " + fun(site_name)

    # Decorator returns a function
    return addWelcome

@decorate_message
def site(site_name):
    return site_name;

print site("StackOverflow")

Out[0]: "Welcome to StackOverflow"

Decorators can also be useful to attach data (or add attribute) to functions.

A decorator function to attach data to func

def attach_data(func):
       func.data = 3
       return func

@attach_data
def add (x, y):
       return x + y

print(add(2, 3))
# 5    
print(add.data)
# 3

Decorator is just a function that takes another function as an argument

Simple Example:

def get_function_name_dec(func):
  def wrapper(*arg):
      function_returns = func(*arg)  # What our function returns
      return func.__name__ + ": " + function_returns

  return wrapper

@get_function_name_dec
def hello_world():
    return "Hi"

print(hello_world())

I'm going to use a code to response this.

What I need?: I need to modify math.sin()'s definition to add 1 always to the sine of a value

Problem: I do not have math.sin() code

Solution: Decorators

import math

def decorator_function(sin_function_to_modify):
    def sin_function_modified(value):
        # You can do something BEFORE math.sin() == sin_function_to_modify call
        value_from_sin_function = sin_function_to_modify(value)
        # You can do something AFTER math.sin() == sin_function_to_modify call
        new_value = value_from_sin_function + 1;
        return new_value;

    return sin_function_modified

math.sin = decorator_function(math.sin);

print(math.sin(90))

Return of math.sin(90) before implement decorators: 0.8939966636005579

Return of math.sin(90) after implement decorators: 1.8939966636005579

Related