10 Python Anti-Patterns: Stop Writing Over-Engineered Chaos

ArjanCodes////4 min read

The Trap of Clever Python Code

Python often rewards cleverness, but that flexibility serves as a double-edged sword. Developers frequently stumble into patterns that look sophisticated yet cripple long-term maintainability. These are anti-patterns: solutions that seem effective in the moment but create friction as a codebase scales. Writing clean code isn't about using every feature the language offers; it's about knowing when to keep things simple. From misusing exceptions to over-engineering with unnecessary design patterns, let's break down the habits that are likely hurting your projects.

Control Flow and Structural Missteps

A common habit is using exceptions for control flow. This stems from the Python philosophy that it is "easier to ask for forgiveness than permission" (EAFP). However, nesting try-except blocks to handle standard logic—like switching to a backup API—makes code unreadable and slow. Exceptions are for exceptional circumstances, not for expected logical branches.

Similarly, many developers coming from Java backgrounds wrap utility functions in classes containing only static methods. This is unnecessary. In Python, modules are the natural namespace. If a class doesn't maintain state or provide an instance, it should just be a collection of functions in a .py file.

# Anti-pattern: Using classes for simple functions
class DataUtils:
    @staticmethod
    def clean_text(text):
        return text.strip().lower()

# Better: Just use a module-level function
def clean_text(text):
    return text.strip().lower()
10 Python Anti-Patterns: Stop Writing Over-Engineered Chaos
10 Python Anti-Patterns That Are Breaking Your Code

The Dangers of Surprising Behavior

Overriding dunder methods—like __new__—to return unexpected object types is a recipe for debugging nightmares. If you call an initializer for a Payment class, you expect a Payment object, not a sub-instance of StripePayment or PayPalPayment. This "magic" breaks the expectations of linters and teammates alike. Instead of complex inheritance magic, use a simple dictionary or an Python to map types to specific functions.

We also see this with custom decorators used solely for dependency injection. Wrapping a main function in a three-layer-deep nested callable just to pass a configuration file adds immense cognitive load. Often, a direct function call to load_config() is the cleaner, more transparent choice.

Over-Engineering and Inappropriate Intimacy

Design patterns like the Abstract Factory or Visitor pattern are powerful tools, but they often lead to over-engineering. If a dictionary and two functions can solve the problem, creating five classes and an abstract base class is a waste of time. The most important principle is keeping it simple.

Furthermore, keep an eye out for Inappropriate Intimacy, where two classes know too much about each other’s internal structures. If an exporter function has to know the exact attribute names of a Report object, they are too tightly coupled.

# Improved Abstraction with Protocols
from typing import Protocol

class Exportable(Protocol):
    def to_csv(self) -> str: ...

def export_to_csv(item: Exportable):
    print(item.to_csv())

By using Python, you decouple the logic. The exporter doesn't care if it's handling a Report or a Budget, as long as the object follows the contract.

Prerequisites

To get the most out of these refactoring techniques, you should be comfortable with basic Python syntax, the concept of classes and inheritance, and how modules function as namespaces. Familiarity with decorators and type hints will help in understanding the more advanced structural changes.

Key Libraries & Tools

  • Python Standard Library: Specifically os.walk, json, and typing.Protocol for structural integrity.
  • Lokalise: An AI-powered platform used to manage translations and move hardcoded strings out of the UI.
  • Pydantic / Click / Typer: Mature libraries that replace the need for custom-built boilerplate for data validation and CLI interfaces.

Syntax Notes

  • Dunder Methods: Special methods like __call__ allow objects to be treated as functions, which can be a cleaner alternative to complex decorators.
  • Type Annotations: While ignored at runtime, these are vital for static analysis and making code self-documenting.
  • Wildcard Imports: Using from module import * is an anti-pattern because it pollutes the namespace and obscures the source of functions.

Practical Examples

Instead of hardcoding every UI string in a Streamlit app, which makes internationalization impossible, use a translation key system. By calling a translation object, you can switch the entire app's language—from English to Dutch, for example—by changing a single environment variable.

Tips & Gotchas

Avoid the urge to "reinvent the wheel." Python is famous for having "batteries included." Before writing a recursive file walker, check if os.walk already exists. The ecosystem is your greatest asset; leverage mature third-party libraries rather than building custom, unproven solutions for standard problems.

Topic DensityMention share of the most discussed topics · 13 mentions across 7 distinct topics
Python
54%· products
Java
8%· products
Lokalise
8%· companies
Pandas
8%· products
PayPal
8%· companies
Other topics
15%
End of Article
Source video
10 Python Anti-Patterns: Stop Writing Over-Engineered Chaos

10 Python Anti-Patterns That Are Breaking Your Code

Watch

ArjanCodes // 25:16

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!

What they talk about
AI and Agentic Coding News
Who and what they mention most
Python
27.3%3
Python
18.2%2
Python
18.2%2
4 min read0%
4 min read