Improve Your Python Code Readability and Maintenance by Avoiding These 3 Mistakes
TLDR; Avoid these 3 mistakes for clearer Python code: overusing dictionaries, using strings for variations, and not using type hinting. Consider data classes and enums for structured data and variations, and use type hinting for readability.
When you are trying to prototype an idea or start a new project in Python, it is generally a quicker process than using other languages in most cases. The simplicity of Python's syntax side by side with its dynamic nature is extremely attractive to anyone starting, but this can also be detrimental in the long run. As you advance in your career, you begin to see how shipping new software is just part of the big picture, and there is a larger aspect called maintaining old software, or as we call it, legacy code.
with that said, here are some mistakes to avoid if you want to make it easier for people and your future self to maintain your code.
Mistake #1 Using dictionaries for everything
Dictionaries are a fantastic data structure and incredibly powerful in Python, but overusing them can make your code difficult to trace.
The primary issue with dictionaries is their lack of a defined structure. Without a clear structure, it's challenging to know what to expect from a dictionary at a specific point in your software. What keys are present, and what types of data are held within? It will require extra effort from you to ensure the structure and the existence of certain keys/values. To avoid this, you can use Data classes.
The main advantage of Data classes is the presence of a defined structure, which can be extremely helpful if your data has a consistent structure that will always be satisfied, for example.
from dataclasses import dataclass
@dataclass
class User:
name: str
url: str
age: int
address: str
new_user = User(name="Mo", url="www.m-ashour.space", age=28, address="Earth")
#Using dataclass, you can access the data inside directly like this
>> new_user.name
>> new_user.age
#compare using dataclasses here with using dict
new_user_dict = {"name":"Mo", "url" : "www.m-ashour.space", "age":28, "address":"Earth"}
#here, you don't have an enforced defined structure and you are vurnable to more mistakes
>> new_user_dict["name"]
>> new_user_dict["age"]
As you can see, the advantage of a defined structure is quite obvious even in a very simple example. imagine yourself reading this code in 3 years, which one would be easier to maintain and read?
Of course, it's not always the right choice!
Data classes are easier to write and maintain, but they are not the most lightweight, if performance is an issue, you might look at other solutions which we can discuss in another article.
Mistake #2 Using Strings to distinguish variations
Strings are powerful and incredibly useful, but misusing them can lead to numerous problems and potential issues.
To represent variations, you need a well-defined and structured method to explicitly implement them and limit the options to only the supported variations. This way, you can prevent any potential issues arising from referring to or passing a non-supported, non-implemented variation. In this case, using strings will not fulfill these requirements, but using Enums will. Allow me to use the same example.
Don't
from dataclasses import dataclass
@dataclass
class User:
name: str
url: str
age: int
address: str
#let's add a user type
user_type: str
#here, using user_type as string, will not give any indication on what user types we have
Please Do
from dataclasses import dataclass
from enum import Enum
class UserType(Enum):
STANDARD = "STANDARD"
PRO = "PRO"
BUSINESS = "BUSINESS"
@dataclass
class User:
name: str
url: str
age: int
address: str
user_type: UserType
#here you can clearly understand the types of users that the code supports
As you can see, Enums can provide an incredible boost in understanding the code and can provide help in how to use it. it's a timeless documentation on its own, even on the basic level. There is more to Enums, but that's a separate topic for a separate post.
Mistake #3 Not using type hinting
Even though type hinting in Python doesn't enforce anything or check the types during runtime (since we don't have compile time), it still provides readability on various levels.
Type hinting wasn't introduced in Python until version 3.5. While it's not native to the language or fully matured, it still offers readability and productivity enhancements when maintaining existing code or writing new code. Current Code editors and IDEs now have good integration with it, and depending on the types you hint your variables with, they can suggest appropriate methods. Additionally, it serves as basic documentation for your functions.
For example,
from typing import List, Tuple
def draw_line(x,y):
.....
#using type hinting
def draw_line(x:List[float], y:List[float]) -> List[Tuple[float,float]]:
.....
Can you see the difference in readability? this is a big difference for anyone reading your code (including you).
Conclusion
In this Article, I walked you through 3 main mistakes that can make your code more trouble to maintain and read. So to sum it up
Data classes are a better option than Dicts for structured well-defined data bundles
Enums speak louder and clearer than Strings when it comes to domain-defined variations
Type Hinting is a great advisor and a future guide for your colleagues and your future-self
These are not the only mistakes, there are more that we can learn from. Let me know in the comments about some of them!
See you in the next one!
Subscribe to my newsletter
Read articles from Mohamed Ashour directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Mohamed Ashour
Mohamed Ashour
Spending most of my time writing code, designing architecture, and creating pipelines to generate data. And the rest of it learning new things to write about.