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 Javascript, browser makers would do well to just adopt CoffeeScript 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 range() 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 solve puzzles.

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 looked back.

(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 copy() 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 common operation...

(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):
  print i
  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?