Beyond the Class Keyword: Cleaning Up Python Object-Oriented Design
Python is a multi-paradigm language, but developers often treat it like Java, forcing every piece of logic into a class structure. This obsession with Object-Oriented Programming frequently leads to "spaghetti code"—not because the code is messy, but because the abstractions are unnecessary. Writing clean Python requires knowing when to use a class and, more importantly, when to walk away from one.
Functions Masquerading as Classes
A common anti-pattern involves creating a class that contains only an __init__ and a single method. If your class doesn't store state that multiple methods need to access, or if you never intend to create multiple instances with different data, you have written a function with extra steps. This adds boilerplate and forces the user to instantiate an object just to perform one action. In Python, Python Functions are first-class citizens. If you just need to load data or process a single input, a standalone function is more readable, easier to test, and significantly faster to implement.

The Module vs. The Utility Class
Developers coming from static languages often create classes filled entirely with @staticmethod decorators. These "utility classes" act as namespaces for related functions, like string manipulation or math helpers. However, Python already has a built-in namespace tool: the module. Instead of a StringUtils class, create a string_utils.py file. This allows you to import exactly what you need without the overhead of a class structure that will never be instantiated. It respects the Python philosophy of simplicity and prevents misleading users into thinking there is internal state to manage.
Flattening Inheritance with Composition
Deep inheritance hierarchies are brittle. When a sub-class depends heavily on a super-class, a minor change at the top of the tree can break the entire branch. Many developers use inheritance to describe roles—like Manager inheriting from Employee—but this creates a rigid structure. A better approach is composition. By giving an Employee a Role attribute (perhaps using a Python Enum), you decouple the identity from the behavior. This makes the code easier to extend; adding a new role doesn't require a new class, just a new enum value or instance.
Embracing Abstractions and Protocols
Hard-coding dependencies inside a method makes testing a nightmare. If a process_order function creates its own EmailService internally, you can't test the order logic without actually sending an email. The solution lies in Dependency Injection and abstractions. By using Python's Protocol from the typing module, you can define a contract. As long as an object has a send_email method, the order processor doesn't care if it's a real SMTP client or a mock object for testing. This decoupling is the hallmark of professional software design.
The Balance of Encapsulation
Encapsulation protects the internal state of an object, ensuring that data remains consistent. If you have a BankAccount, you shouldn't let external code modify the balance directly; you should use withdraw and deposit methods that include validation logic. However, don't over-engineer simple data containers. If a class is just a name and an age, adding Getters and Setters is just noise. For these cases, Python Data Classes provide a clean, concise way to represent data without the boilerplate, allowing direct attribute access while maintaining the benefits of a structured object.
Clean Python isn't about using every feature the language offers. It is about choosing the simplest tool that solves the problem. Whether that's a function, a module, or a well-designed class, the goal remains the same: maintainability and clarity.
- Dependency Injection
- 17%· products
- Object-Oriented Programming
- 17%· products
- Python
- 17%· products
- Python Data Classes
- 17%· products
- Python Enum
- 17%· products
- Python Functions
- 17%· products

Avoid These BAD Practices in Python OOP
WatchArjanCodes // 24:42
On this channel, I post videos about programming and software design to help you take your coding skills to the next level. I'm an entrepreneur and a university lecturer in computer science, with more than 20 years of experience in software development and design. If you're a software developer and you want to improve your development skills, and learn more about programming in general, make sure to subscribe for helpful videos. I post a video here every Friday. If you have any suggestion for a topic you'd like me to cover, just leave a comment on any of my videos and I'll take it under consideration. Thanks for watching!