Handy Python Snippets for Cleaner Code

Dynamically call a function, list functions with a specific part of their name, and more

Tate Galbraith
Nov 12, 2020 · 4 min read
Laptop on a desk
Laptop on a desk
Photo by Rich Tervet on Unsplash.

Refactoring existing code effectively is an art. If you have ever inherited someone else’s code or even looked back at your own after some time, you know how trying this process can be. Oftentimes, features are made and bugs get fixed under tight timelines, which can lead to sloppy, inefficient code.

That’s completely fine. You’re allowed to commit some bad code from time to time. What is imperative is that you can identify the bad code and always return to fix it.

In this article, we’re going to look at some small segments of Python code that make refactoring for cleaner code easier. In most cases, these use simple, standard library functions and don’t obfuscate intent behind exceedingly complex algorithms or dense one-liners. When you’re refactoring code, you want a good balance between being concise and readable. Let’s take a look at a few examples.

Dynamically Calling Functions

def call_func(name):
klass = MyClass()
return getattr(klass, name)()
call_func('function_name')

If you encounter sections of code where you won’t necessarily know the name of a function you wish to invoke until later, this is the answer. By using the built-in Python function getattr, you can call a function by name using a string. This is great for reducing tightly coupled code and improving extensibility. If you reduce hard-coded function names and allow more flexibility, then there is a strong chance your code will break less.

Using this simple method also reduces the overhead for other developers to add functionality to existing code. If all you have to do is add a new function to a class and it becomes immediately usable, that reduces complexity and makes code easier work with.

You can read more about the getattr function in the documentation.

Using Destructuring Assignment

var_one, var_two = [1, 2]

You’ve probably heard about this concept a million times before, but it bears repeating: Use destructuring assignment where possible to display values and convey intent more clearly. When you access a list or an array by index values, you inadvertently hide your intent. Referencing values by a clear variable name assigned through destructuring assignment makes your code easier to read.

In the example below, we have some data about a person on a list. This data includes basic information like the person’s name, age, and profession. Let’s assume for the sake of this example that this is part of a response we received back from a web request and that we’d have to parse multiple responses just like this. If we wanted to get the person’s name, we could simply access it by the index value:

person = ['Bill', 26, 'Programmer']print(person[0])

This is sloppy and hides intent if you ever reference it more than once. Referencing person[0] all over the place in your code will make it difficult to interpret what value that should be. There is a very simple fix for this that does not hide your intent and makes your code more readable. Simply assign this to a variable and, if possible, destructure the entire list into appropriately named variables as well. Let’s look at an example of putting this into practice:

person = ['Bill', 26, 'Programmer']name, age, profession = personprint(name)

Now if you need to reference the name later, you will be doing so via a named variable vs. an index value. This works well for response data that you’ll likely know the structure of. As long as the person’s information is always in the same order, you can destructure and assign everything over and over again to avoid using index values.

Listing Functions With a Specific Pattern

In this example, let’s assume we have the class above containing a large number of functions. Some of these functions serve a special purpose and should be dynamically accessible. We want any special function that we add to this class to be immediately picked up by the rest of our code so that it begins working right away. One way to accomplish this is simply by using dir on the containing class.

If you pass a class to dir, it will list all of the attributes for that object. This includes the names of its functions. By filtering for a prefix, suffix, or included keyword in the string name, we can group the functions of this class into different categories. This allows us to “pick up” new functions whose names include a keyword and either call them all or perform other logic with them later on in the code.

Check out more on the built-in dir function in the docs.

Passing Multiple Function Arguments as a Dict

There is a strong chance that you’ve come across something similar to this before while refactoring code:

Although certain formats of this indentation style might technically be allowed in PEP8, I personally do not enjoy looking at heavily indented function arguments. You are forced to move your eyes all the way over to the right, some IDEs don’t play nice with this indentation, and using this style inhibits future extensibility.

One option to consider for improving readability and reuse when there are a lot of function arguments is to pass them in dict form. Here is an example of this:

Using the ** operator on the dict as you’re passing a dict to the function allows you to unpack all of the arguments successfully (instead of accidentally passing the dict object itself). Although this method does add another variable and a separate data structure, it improves overall readability when there are a larger number of arguments. Moving the function call around or referencing multiple calls to the same function with the same (or slightly tweaked) arguments now becomes infinitely easier and requires less overall modification.

Conclusion

Thank you for reading! I hope these code snippets will help improve your efficiency the next time you find yourself picking apart some Python code.

Better Programming

Advice for programmers.

Sign up for The Best of Better Programming

By Better Programming

A weekly newsletter sent every Friday with the best articles we published that week. Code tutorials, advice, career opportunities, and more! Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Tate Galbraith

Written by

Software Engineer @mixhalo & die-hard Rubyist. Amateur Radio operator with a love for old technology. Tweet at me: https://twitter.com/@Tate_Galbraith

Better Programming

Advice for programmers.

Tate Galbraith

Written by

Software Engineer @mixhalo & die-hard Rubyist. Amateur Radio operator with a love for old technology. Tweet at me: https://twitter.com/@Tate_Galbraith

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store