Python is awesome! So why do people hate Python? After some highly non-scientific, Internet-based research, these are the reasons I encountered most often. I found many more, but most of them were so ridiculous that I wouldn’t even dare to repeat them here.
I won’t link to sources or apply naming and shaming. Consider this read just for fun, but with an educational touch!
Disclaimer: no feelings or programmers were hurt while writing this article, but some feelings might get hurt while reading it. If you have a heart condition and love Python, perhaps you better skip this one.
Table of Contents
Indentation instead of curly braces
Many people complain that Python relies completely on indentation to create blocks of code. As you know, indentation is not optional in Python. The complaints vary but are often one of the following.
It’s hard to see where a function ends
That’s true if you write huge Python functions. But it would help if you didn’t write huge functions at all. In fact, this applies to any language, not just Python. A function should do one thing and do it well. If you find yourself writing a multi-page function, you should start splitting it up into smaller functions that do one thing.
This doesn’t just result in clean, readable code. It also results in testable code. It’s easy to create unit tests for small functions that do one thing with no side effect. When you create large functions that do many things, you can write integration tests at best.
When using conditions, it’s an indentation mess
The bottom line here is the same: if you write conditional statements, you should create functions if there are more than a couple of lines per condition. A somewhat silly example:
print("All done, do you want to send the email right now?") answer = input() if answer == 'yes': send_the_email() elif answer == 'no': store_the_result_for_later() else: handle_unknown_input()
If each condition would contain 5 to 15 lines of code, with their own indentation, conditionals, and loops, then yes: it would have looked messy. But in this way, with the function calls, it looks super clean.
So instead of writing all your code inside the conditional statement, put your code into clearly named functions and call those instead. You don’t even have to look at the functions’ content because it is so obvious what they do, based on their names.
You can choose any number of spaces (or tabs)
Python will indeed accept any number of spaces or even tabs, as long as you consistently do it that way. So the following code, with an indentation factor of 1, is just as valid as the code above:
if answer == 'yes': handle_yes() elif answer == 'no': handle_no() else: handle_unknown_input()
How much of a problem is this, though? We all use IDEs or advanced editors, and we all know and learn to style according to style guides, like PEP8. In fact, all IDEs will auto-indent for you, making this a non-problem. Many IDEs, including the popular Visual Studio Code, even support automatic styling plugins, like autopep8 and flake8.
And to what extent is this not a problem of all languages, even those that use curly braces to create code blocks? There’s always the issue of code style, no matter the language. You’ll have to pick a style and stick to it. I strongly suggest the usage of one of the auto formatters; they are great and save you a lot of hassle trying to format your code.
Multiple Python versions
I’ve seen people hating on Python because there are two versions of Python, namely Python 2 and Python 3. To make things worse, they are often installed alongside each other in Linux. Although there has been a time where both were prevalent (and incompatible), this is much less of a problem today than it was, say, 5 years ago.
These days, most projects have converted their code to Python 3, but that was not the case in the past years. Unfortunately, many Linux distributions have been forced to ship with two versions of Python because so many packages took their sweet time to convert to Python 3.
To summarize: yes, it has been a valid point for a few years, during the transition to Python 3, but it’s mostly solved by now.
If you still have Python 2 code lying around, check out our article on how to migrate to Python 3. If you want to know which versions of Python you have installed, read how to check your Python version.
For many, it’s the first (and last) language
Many teachers use Python to teach their students the principles of programming. Understandably so! I firmly believe it’s a great language for beginners. Hence, for many people, Python is the first programming language they learn. For a part of those, it’s also the last. Programming is not for everyone, and that’s fine. Some will give up.
So a lot of complaints about Python are actually complaints about programming in general. It just happens to be the first (and for some: last) programming language for these complainers. For example, the people that give up on learning programming tend to complain about Python specifically instead of programming in general.
Besides that, Python is incredibly popular. It consistently ranks in the top 3 of most used languages globally, so it’s bound to receive a lot of hate as well. That’s just the way things are in this world.
Python is slow
Here’s another reason why people hate Python. And indeed, Python was not designed to be the fasted language in the world. An there’s also the Python GIL, which really is not such a big problem as people make it sound.
In fact, Python as a language tends to choose well-readable, clean code above raw speed. So yes, Python is not the fastest language. Still, I notice many people complaining about it without really having a speed problem, or at least without trying to improve their own inefficient code first.
If you do have a speed problem in Python, there’s a lot you can do to speed up your code. One of them is using concurrency, as outlined in our tutorial. But more often than not, it’s just a matter of optimizing your code.
Some stuff you can look into:
- caching,
- bloom filters,
- using the proper data structures,
- reduce the amount of work you do inside loops,
- prevent recursion.
Alternatively, you can look at faster Python implementations, like PyPy and CPython. And if that’s not enough, many of the most popular Python packages have their core functionality implemented in C, like NumPy. So you may get better results by replacing your code with functionality from libraries here and there.
Python doesn’t scale to large projects
I’ve seen people defending Python in discussions, only to conclude with the remark that Python is a scripting language and that it doesn’t scale well into larger applications. And it’s simply not true. I know of multiple large applications that are doing fine. In fact, Python has all the tools to scale:
- You can chop up the project into multiple packages if you want
- You can use modules
- It supports object-oriented programming
Python scales just as well, sometimes even better, as any other language. One big project, which I use day and night in my home, is Home Assistant. It’s living proof that you can write large, complex applications with Python.
Python has ugly, built-in global functions
In object-oriented languages like Java, there are no global functions. Examples of such functions in Python are len()
and print()
.
For len()
, the complaint I often read is that the length should be part of the object, not a global function. For example, to get the length of a Python list, why is there no length() method like this:
mylist = [1, 2, 3] # This won't work mylist.length() # And this won't work either mylist.length # You need to use len: len(mylist) 3
There are reasons why Python has the len()
function instead, though. It’s actually an intentional design choice.
In other languages (Java, I’m looking at you), you can get the length by calling a method on the object. But which method? Is it:
.length()
.size()
numItems()
- …etcetera
Or is it a variable, like .length
or .size
? I’ve seen all these and even more variations in my life as a Java developer. It makes sense to standardize such a common operation. If your object in Python implements the __len__()
dunder method, the len()
function will work. You just need to get used to it.
Python is just a typeless scripting language
This is somewhat True
and False
. Python is a great scripting language. I love how it allows me to hack together a quick script to perform some tasks without defining types explicitly beforehand. It allows me to prototype and run quick little experiments.
This flexibility in typing is called dynamic typing. The variable itself doesn’t have a type, but the object you create does. Besides that, Python is a strongly typed language, meaning that an object’s type will not change once it is created. For example, the string “2” will not magically turn into a number when you use it in an equation like “2” + 2. Python will throw a TypeError if you do so.
With the recent addition of explicit typing support, Python offers a nice hybrid model. I feel like they’ve hit the sweet spot. If you’re hacking away, leave out the typing stuff. But if you’re writing applications, you can (and should) specify types. The interpreter will ignore them, but your linter and/or IDE can use the type hints to catch potential problems. Even better: your IDE will offer you superb auto-completion because it now knows the types of all your objects, without having to guess.
I get the feeling that the Python community has embraced the new explicit typing. As an example, the popular API framework FastAPI uses typing extensively. It’s one of the reasons it’s so easy to use: because of explicit typing, you get great auto-completion in your Python IDE too.
So what about you? Which parts of Python do you love, and which parts grind your gears? Let us know in the comments section!