Understanding Basic Decorators
In this step, we will introduce the concept of decorators and their basic usage. A decorator is a function that takes another function as an argument, adds some functionality, and returns another function, all without altering the source code of the original function.
First, locate the file decorator_basics.py in the file explorer on the left side of the WebIDE. Double-click to open it. We will write our first decorator in this file.
Copy and paste the following code into decorator_basics.py:
import datetime
def log_activity(func):
"""A simple decorator to log function calls."""
def wrapper(*args, **kwargs):
print(f"Calling function '{func.__name__}' at {datetime.datetime.now()}")
result = func(*args, **kwargs)
print(f"Function '{func.__name__}' finished.")
return result
return wrapper
@log_activity
def greet(name):
"""A simple function to greet someone."""
print(f"Hello, {name}!")
## Call the decorated function
greet("Alice")
## Let's inspect the function's metadata
print(f"\nFunction name: {greet.__name__}")
print(f"Function docstring: {greet.__doc__}")
Let's break down this code:
- We define a decorator function
log_activity which accepts a function func as its argument.
- Inside
log_activity, we define a nested function wrapper. This function will contain the new behavior. It prints a log message, calls the original function func, and then prints another log message.
- The
log_activity function returns the wrapper function.
- The
@log_activity syntax above the greet function is a shortcut for greet = log_activity(greet). It applies our decorator to the greet function.
Now, save the file (you can use Ctrl+S or Cmd+S). To run the script, open the integrated terminal at the bottom of the WebIDE and execute the following command:
python ~/project/decorator_basics.py
You will see the following output. Note that the datetime will vary.
Calling function 'greet' at 2023-10-27 10:30:00.123456
Hello, Alice!
Function 'greet' finished.
Function name: wrapper
Function docstring: None
Notice two things in the output. First, our greet function is now wrapped with the logging messages. Second, the function's name and docstring have been replaced by those of the wrapper function. This can be problematic for debugging and introspection. In the next step, we will learn how to fix this.