14 May 2015
I've been learning and using Python quite extensively for the past few
years, and every time I mention that to someone they go, "ugh! that
language with the indentation-based syntax". And I'm like, really?
That in my book is a quality of the language. Seriously, don't you
indent your code meticulously anyway? Python simply spares you from
also having to bother with curly braces, or extra keywords.
But the fact that people complain about that mostly tells me they
haven't used Python enough to discover some of its real downsides.
It has plenty, and they're becoming quite familiar to me as of late.
So let me give you some good reasons to hate Python, before I
explain why I favor it over other programming languages anyway.
The bad of Python
The rules for breaking up a line of code are a mess. This is where
freeform syntax has a massive advantage, but if you can't have that,
at least choose a clear syntax for continuation lines and leave it at
that. Come on, folks, Fortran got that right in 1956!
The explicit "self" argument to class methods, which is extraneous
and obnoxious. Whose bright idea was that?! It's not like any sane
programmer is going to bend the convention and use something else.
Might as well make it implicit, like in... oh... every other
programming language. As it is, you're only forcing me to strain my
articulations typing reams of entirely avoidable boilerplate.
(That said, all new languages would do well to adopt the "@" syntax
from Ruby, like CoffeeScript has. But until then, let's take some baby
steps at least.)
(Note to the note: rather than piling up haphazard additions to
instead. Not that I'm holding my breath... it makes too much sense for
your average software company.)
Python really, really needs a numeric for loop, because
just doesn't cut it. For one thing, all too often I need the iteration
to stop at the limit, not before it, and I must remember to put a
"+ 1" there. Or the limit is calculated, and I need to stop and think
about offsets. Dear Python, you were supposed to help me, not make me
Also, why oh why do I have to create a big-ass (iterator) object just
to loop over a few numbers? Because all too often that's all I'm doing,
and the language saddles me with a huge performance penalty that could
have been easily avoided. Not that I expect that much performance when
working in Python, but senseless waste of resources is one of the
biggest problems with modern computing. So, yuck.
Last but not least, an invisible issue that's nevertheless just daft: using exceptions to terminate loops. Which breaks the most basic
rule about them, namely that they should only be used in, you know,
exceptional situations! That's the kind of abuse that earned
exceptions the terrible reputation they have but don't deserve.
The good of Python
If you've been reading so far, I guess you want to give Python a
chance anyway. Which is good, because as Bjarne Stroustrup would say,
the only languages nobody complains about are those nobody uses. So
let's see the flip side as well.
You can learn Python almost without meaning to. It happened to me
around 2009, when I was trying hard to learn Perl, with manuals, code
exercises, the whole deal. It never stuck. But at the same time, I
read through the official Python tutorial once or twice, simply out of
curiosity. Browsed some code samples online, played a little with the
interactive console... A few months later, I realized I still didn't
know Perl one bit, but I had become fairly proficient in Python.
Despite trying hard to learn the former, but not the latter. I never
(Now that I think of it, that was my second attempt to learn Perl. My
first one, in 2001, ended up with me learning PHP instead. But at
least back then I could blame my own inexperience.)
The data structures are incredibly powerful. As I posted not so
long ago on Twitter, we talk a lot about code, but programming is data,
data, data. And Python delivers more than any other language I know.
Lists, dictionaries, tuples, sets, strings... each with a litany of
useful methods not easily found elsewhere. Like the ability to
a list and iterate over the copy while safely changing the original.
Something that can be as easy as
a = [1, 2, 3]; x = 2
if x in a: a.remove(x)
Java, of all things, can do the same. Why can't JS? It's a very
(To criticize a little more, removing an element from a set that
wasn't a member in the first place should be a no-op instead of
raising an exception. It's basic math. Never break the basic rules
of math in a programming language.)
Speaking of expressiveness, list comprehensions really make a
difference. You won't need them in many places, but when you do they
result in much shorter and clearer code. And with the option to make
a generator instead, you can also trade storage space for speed. Which
helps a lot more with software performance than s****d bit-fiddling
tricks, as a general rule. It's exactly the kind of decision languages
should leave to the programmer.
As a final point, I nearly forgot to talk about operator overloading.
Some people find it confusing, but I say it's an essential feature if
you want objects to be first class citizens of a language. And Python
has a much nicer syntax for it than C++. Besides, it just makes sense:
in math, you denote matrix multiplication with the same symbol you use
for numbers; why should it be any different in programming, which is
just applied math?
But I'm running out of space here. Be fair to Python, is all I'm
saying. And have fun coding.
Python does indeed let you exit a loop early, with break (just like in C-family languages):
for i in range(500):
if i > 2: break
Also, range iterator objects are pretty lightweight.
I dislike the whitespace-tokenization mostly because now I’m not sure if the code I wrote above is going to be formatted reasonably for this comment system.
My big complaint with Python is the lack of an increment or decrement operator. In Python, both ++i and –i are perfectly valid code – that do absolutely nothing. (–x parses as -(-x), and unary + is a no-op that they maintained for symmetry with -.)
That’s not what I meant. Python signals the normal end of a loop with an exception, internally. How exactly is the fact that a loop ends… unexpected?