diff --git a/content/blog/pydecorators.md b/content/blog/pydecorators.md new file mode 100644 index 0000000..0d50a2a --- /dev/null +++ b/content/blog/pydecorators.md @@ -0,0 +1,66 @@ +--- +title: "Quick Python: Decorators" +date: 2020-03-30T18:07:14-04:00 +draft: false +tags: ["python"] +--- + +[Geir Arne Hjelle](https://realpython.com/team/gahjelle/) at Real Python wrote a great post called [Primer on Python Decorators](https://realpython.com/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 + +```python +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... + +```python +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. + +```python +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}!" +``` +