Using Functions for Dependency Injection and as Callback in Python

Although implementing Dependency Injection design pattern and Callbacks can be implemented in most programming languages (even in VB6), it’s just cleaner/neater to do in Python.

These are also scenarios or use cases where you intentionally would pass the function object instead of it’s return value.

Function as dependency

To write a function that behaves differently or dynamically at runtime (depending on data or condition), we can accept a function object as one of the parameters.

Since we’re only passing the function object, it’s execution can be delayed, in this case when we’re inside our wrapper function.

Here’s a simple “transform” function that takes in a text/string and a function object as parameters. We use this by passing any string, followed by a function that will be applied to the string we passed. For simplicity, we’re just going to pass the built-in functions “str.upper” and “len” to convert the text to upper case and get its length respectively.

And this is what the result looks like:

Function as callback

Another use of passing function as object is for callbacks, and most (if not all) GUI (Graphical User Interface) frameworks in Python requires a function object as callback on events (ex. click event).

We could also design a system that can reroute the flow depending on condition using callbacks.

To illustrate this, let’s pretend we’re building part of the on-boarding system for new hires. We want to make each function distinct (or have a single-responsibility) but also flexible that it can behave differently depending on data.

Simple callback

Here’s a function that registers an employee id into the company database, but the post-processing is delegated to a different function at runtime.

When you run this code, this is what you’ll see:

After running the “register_employee” function, it then executes the “enroll_id” function. Note that we passed it as an object (we didn’t execute it).

Advanced callback

We can do a different version of this on-boarding system and assign a different process (or function) based on (say) the civil status of the employee.

Here’s the modified code:

In this version, we added a “civil_status” parameter and made the post reg function as plural (added “s” to it). We also added 2 new functions, one is for processing single employee and another for married ones.

To make it dynamic, we used a dictionary to define the function based on the civil status value. We could use “if..elif..else” but that won’t be as flexible as this.

Lastly we call the wrapper function (register_employee) with different civil status.

Here’s the result:

This isn’t limited to a regular function.

You can apply the same concept on class methods too. So keep exploring and learning!

Source Codes

The source codes used in this blog is on this Git repository:

https://github.com/vegitz/codes/tree/master/0019%20Using%20functions%20for%20DI%20and%20as%20callbacks%20in%20Python

Leave a Comment