website/content/blog/pydecorators.md

1.7 KiB

title date draft tags medium_enabled
Quick Python: Decorators 2020-03-30T18:07:14-04:00 false
Python
true

Geir Arne Hjelle at Real Python wrote a great post called Primer on Python Decorators. I recommend reading that as this post serves mostly as a reminder to myself on how to write a decorator.

I find decorators useful for several reasons

  • Check a pre-existing condition (Is the user logged in?)
  • Perform post processing on function output (Convert to SI units)
  • Expose extra variables for use in the function

Here is a template for how a decorator is written

import functools

def decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        # Do something before
        value = func(*args, **kwargs)
        # Do something after
        return value
    return wrapper

If your decorator takes arguments then there's another layer...

def decorator_with_argument(argument):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # Do something before
            value = func(*args, **kwargs)
            # Do something after
            return value
        return wrapper
    return decorator

Example: Logging

Let's write a decorator that logs the string returned by the function to a file.

def filelog(filename):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            with open(filename, 'w') as f:
                f.write(func(*args, **kwargs))
        return wrapper
    return decorator

@filelog('log.txt')
def greet(name):
    return f"Hello {name}!"