mirror of
https://github.com/Brandon-Rozek/website.git
synced 2024-11-09 18:50:34 -05:00
67 lines
1.7 KiB
Markdown
67 lines
1.7 KiB
Markdown
|
---
|
||
|
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}!"
|
||
|
```
|
||
|
|