Python has an interesting feature called Decorators to add functionality to an existing code. A Decorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its structure. Decorators are usually called before the definition of a function you want to decorate. This is also called metaprogramming because a part of the program tries to modify another part of the program at compile time.
This post will demonstrate how to run another Python feature in Python4Delphi with RAD Studio: Decorators in Python GUI apps and gets the output.
Prerequisites: Before we begin to work, download and install the latest Python for your platform. Follow the Python4Delphi installation instructions mentioned here. Alternatively, you can check out the easy instructions found in this video Getting started with Python4Delphi.
First, open and run our Python GUI using project Demo1 from Python4Delphi with RAD Studio. Then insert the script into the lower Memo, click the Execute button, and get the result in the upper Memo. You can find the Demo1 source on GitHub. The behind the scene details of how Delphi manages to run your Python code in this amazing Python GUI can be found at this link.
Table of Contents
1. Creating Decorators in Python
Let’s go ahead and create a simple decorator that will convert a sentence to uppercase. We do this by defining a wrapper inside an enclosed function:
1 2 3 4 5 6 7 |
def uppercase_decorator(function): def wrapper(): func = function() make_uppercase = func.upper() return make_uppercase return wrapper |
Our decorator function takes a function as an argument, and we shall, therefore, define a function and pass it to our decorator. We learned earlier that we could assign a function to a variable. We’ll use that trick to call our decorator function.
Note that in Python GUI by Python4Delphi, to print the result, you need to state the print() function, it’s not enough just by return statement.
1 2 3 4 5 |
def say_hi(): return 'hello there' decorate = uppercase_decorator(say_hi) print(decorate()) |
Output in Python GUI:
However, Python provides a much easier way for us to apply decorators. We simply use the @ symbol before the function we’d like to decorate. Let’s see that in the practice below:
2. Applying Multiple Decorators to a Single Function in Python
We can use multiple decorators to a single function. However, the decorators will be applied in the order that we’ve called them. Below we’ll define another decorator that splits the sentence into a list. We’ll then apply the uppercase_decorator and split_string
decorators to a single function:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def split_string(function): def wrapper(): func = function() splitted_string = func.split() return splitted_string return wrapper @split_string @uppercase_decorator def say_hi(): return 'hello there' say_hi() |
The output in Python GUI:
From the above output, we notice that the application of decorators is from the bottom up. Since lists don’t have an upper
attribute, the sentence has first been converted to uppercase and then split into a list.
3. Accepting Arguments in Decorator Functions
Sometimes we might need to define a decorator that accepts arguments. We achieve this by passing the arguments to the wrapper function. The arguments will then be passed to the function that is being decorated at call time.
1 2 3 4 5 6 7 8 9 10 11 |
def decorator_with_arguments(function): def wrapper_accepting_arguments(arg1, arg2): print("My arguments are: {0}, {1}".format(arg1,arg2)) function(arg1, arg2) return wrapper_accepting_arguments @decorator_with_arguments def cities(city_one, city_two): print("Cities I love are {0} and {1}".format(city_one, city_two)) cities("Texas", "California") |
Output:
4. Summary
Decorators dynamically alter the functionality of a function, method, or class without having to directly use subclasses or change the source code of the function being decorated. Using decorators in Python also ensures that your code is DRY(Don’t Repeat Yourself). Decorators have several use cases such as:
- Authorization in Python frameworks such as Flask and Django
- Logging
- Measuring execution time
- Synchronization
Check out Python4Delphi which easily allows you to build Python GUIs for Windows using Delphi.