All Articles
Opinionยท6 min read

Stop Writing Python Like It's Java

Most developers who come to Python from Java bring their habits with them. Classes everywhere, getters and setters, checked exception patterns. Here is what to unlearn.

Part of: Python Programming & Development

Most developers who come to Python from Java bring every Java habit with them. The result is Python that technically works but misses everything that makes Python worth using. Here is what to stop doing.

Everything Does Not Need a Class

In Java, every function lives inside a class. That is a language constraint. In Python it is a choice โ€” and usually the wrong one.

# Java brain class StringUtils: @staticmethod def reverse(s): return s[::-1] @staticmethod def is_palindrome(s): return s == s[::-1]
# Python brain def reverse(s): return s[::-1] def is_palindrome(s): return s == s[::-1]

Module functions are first-class citizens in Python. A file is a namespace. If you are writing a class with only static methods and no state, you have written a bad Java class in Python.

Use classes when you have state that belongs together. Not before.

Stop Writing Getters and Setters

Java forces you into getName() and setName() because fields are private by default. Python attributes are public by default. Writing getters and setters for every field is not defensive programming โ€” it is noise.

# Java brain class User: def __init__(self, name): self._name = name def get_name(self): return self._name def set_name(self, name): self._name = name
# Python brain class User: def __init__(self, name): self.name = name

When you actually need validation or computed properties, use @property. It looks like direct attribute access to callers but runs your logic behind the scenes.

class User: def __init__(self, name): self._name = name @property def name(self): return self._name @name.setter def name(self, value): if not value.strip(): raise ValueError("Name cannot be empty") self._name = value.strip()

Now you can add validation later without changing the calling code. That is the point.

Exception Handling Is Not a Safety Net

Java has checked exceptions. The compiler makes you handle them. Developers new to Python often carry this anxiety and wrap everything in try/except.

# Java brain def read_config(path): try: with open(path) as f: return json.load(f) except FileNotFoundError: return {} except json.JSONDecodeError: return {} except Exception: return {}

Swallowing every exception silently is how bugs disappear into production. Catch what you can meaningfully handle. Let everything else propagate.

# Python brain def read_config(path): try: with open(path) as f: return json.load(f) except FileNotFoundError: logger.warning("Config not found at %s, using defaults", path) return {} # json.JSONDecodeError and others bubble up โ€” you want to know about them

Use Pythonic Data Structures

Java developers reach for classes when Python has better built-in options.

# Java brain โ€” a class for everything class Point: def __init__(self, x, y): self.x = x self.y = y points = [Point(1, 2), Point(3, 4)]
# Python brain โ€” right tool for the job from dataclasses import dataclass @dataclass class Point: x: float y: float # Or for simple cases point = (1, 2) # Or named tuples for clarity without overhead from collections import namedtuple Point = namedtuple('Point', ['x', 'y'])

For config-like objects, dataclass gives you __repr__, __eq__, and optionally __hash__ for free.

List Comprehensions Are Not Optional

This is not style preference. Comprehensions are faster and more readable once you internalize them.

# Java brain squares = [] for i in range(10): if i % 2 == 0: squares.append(i ** 2)
# Python brain squares = [i ** 2 for i in range(10) if i % 2 == 0]

The same applies to dict comprehensions, set comprehensions, and generator expressions. If you are building a list by appending in a loop, ask yourself if a comprehension fits.

The Bottom Line

Python rewards terseness, readability, and trusting the programmer. Java rewards defensive verbosity. Neither is wrong in its own context โ€” but mixing them produces the worst of both worlds. When you write Python, write Python.

The single best thing you can do: read other people's Python. The standard library is written by people who have thought hard about idiomatic Python. Read it.

#Python#Best Practices#Code Quality

Want to go deeper?

Python Programming & Development

View Course