Why Python is Better than Java

Reason 1: Mocking.

unittest.mock, Python’s mocking framework is so much more powerful than EasyMock, Mockito, or any other Java mock framework I’ve ever used. You can replace any method you like with essentially arbitrary code. No longer do you have to contort APIs with convoluted dependency injection just to mock out network connections or reproduce error conditions.

Instead you just identify a method by name and module within the scope of the test method. When that method is invoked, the actual code is replaced with the mock code. You can do this long after the class being mocked was written. Model classes do not need to participate in their own mocking. You can mock any method anywhere at any time, in your own code or in dependencies. No dependency injection required. You can even mock fields.

By contrast Java only lets you mock objects (not methods) and only when you have an available API to insert the mock in place of the real thing.

Reason 2: None is its own type.

In Java null can be anything. In Python only None is None. An str can’t be None. A Foo can’t be None. An int can’t be None. Union[None, Foo] is not the same type as Foo. This is beautifully simple and obvious, once you break Java habits of thinking of None as essentially whatever type you need. It helps to find and prevent bugs and reason about code.

Java has had @Nullable and @NonNull for some years now, but these have never been integrated into the language, require special tools to check them, and aren’t nearly as powerful as Python’s simple decision that None is its own thing.

Reason 3: Named method arguments with defaults

These are so much more readable and less error prone than method overloading, I hardly know where to begin. In fact, these are so wonderful I’m tempted to write all my Python code with only named arguments.

Reason 4: Calling super.__init__ last

In Java the superclass constructor is always called first, before any other statements in a subclass constructor. There are reasons for this, but it’s often inconvenient and can require a lot of hanky panky to get values ready before they’re naturally available.

Python is just easier here. Call super.__init__ whenever you’re ready to call it: first, last, in the middle. It doesn’t matter.

Reason 5: f strings

Relatively new in Python — version 3.7? — but far more readable and less error prone than what we had before.

When Java added varargs, printf, and java.lang.Formatter circa Java 1.5, we had decades of experience in C and C++ to teach us this was a bad API that led to dangerous bugs. Sadly, no one paid attention to that. Instead of creating a modern, sane format like Python’s f-strings, they mindlessly copied a misbegotten 30 year old kludge from C. At least Python eventually learned from Java’s mistake even Java didn’t learn from C’s.

Leave a Reply