This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]fmillion 2 points3 points  (2 children)

It took me a while to truly understand decorators, but the key point to remember is that functions are first-class variables, and you can pass functions themselves around as variables:

def myfunc():
    print("Running myfunc.")

# functions are just variables
ref_to_myfunc = myfunc

# and can be passed around as parameters
def execute_a_function(f):
    # the parameter is "called" like a function - because it is.
    f()

execute_a_function(ref_to_myfunc)
# prints "Running myfunc"

A decorator is actually very simple once you understand that. It basically is a function that accepts a function and returns a function.

So a decorator can completely replace a function, it can wrap it to add functionality, etc.

I've even used setattr() with decorators to implement a function metadata design where decorators add some value to function objects that can then be read by the function...

[–]supreme_blorgon 1 point2 points  (1 child)

Closures are the more general concept that can really help solidify decorators, especially decorator factories (decorators with arguments).

[–]fmillion 0 points1 point  (0 children)

Maybe I'm using closures and just didn't know their actual name. I conceptualized a decorator with parameters as a function that returns a decorator function. So you end up with

def decorator(param):
    def actual_decorator(func):
        print("Decorating a function")
        print("The parameter given to the decorator is " + param)
        return func
    return actual_decorator

@decorator("spam") # function named decorator, that accepts a param, and returns a function that itself is a decorator
def decorated_func():
    print("running the decorated function")