Fork me on GitHub

Revisiting Python

2008-12-26

I used to be an avid Pythonista. I poured over Python books, read huge swathes of Python code (including the source of Twisted, which, as its name might imply, I think of as quite a personal accomplishment), and soaked up as much material as I could find. I had survived the relative chaos of Perl, and was relieved to find a more orderly, seemingly sane language to work with. I dove in, and I loved it.

I learned a huge amount during those years; Python was my first OOP language, and cemented what has become my obsession with dynamic, “lightweight” languages. I’ve never studied CS formally (having opted for languages and linguistics instead) so Python’s more draconian rules and academic bent helped temper my more artistic tendencies and pushed me far enough into the land of algorithms, data structures, and big O notation so not to be seen as a complete dilettante by later CS nerd colleagues.

One day, I stumbled across a lone copy of Programming Ruby by chance at at bookstore (back when you just didn’t find Ruby books). At the time, I thought of Ruby as merely “a Japanese Perl,” so I only picked it up on a whim — but only a few chapters in, I was completely hooked.

Although I continued to use Python (and PHP) professionally for the next couple of years, and very successfully — I spent my spare time on Ruby, and became very active in the community. In 2004 I fully switched, and became a professional Ruby developer.

I haven’t looked back.

Okay, looking back

Recently I’ve had the need to do a proof-of-concept across multiple “production quality” OO languages, so it seemed only natural to dig back into Python a bit.

I discovered a language that had matured significantly with a smart community — that now included some “younger” blood and a fair bit of excitement.

So, some specifics, maybe?

First of all, let me add a disclaimer.

As I’ve stated, I haven’t touched the language in years, and I’m many a code kata from anywhere near full competency, let alone best-practices. The following may be completely unadulterated bullshit, and since it’s largely based on Python 2.6 vs 3.0, may be a bit outdated as well. I heartily welcome comments from people who care deeply about Python and can point out better ways to approach things, or simple flaws in my judgment.

Random feelings

So here you go, the bad in with the good.

Python feels clean. I know I’m writing something for a computer, and I seem to focus on the implementation vs the API first when coding Python. This is kind of satisfying. I’m not sure if this is good or bad.

I can’t help but love packages. Although they can be a horrific, academic mess (ie, Java), in many cases a file-based approach removes a lot of complexity. The Ruby community adheres to a lot of different ephemeral “standards” on how to split code between files, and it can be exhausting worrying about it— as a perfectionist I’m a constant fiddler, and worrying about how to split up a module is simply too trivial to be productive.

I love list comprehensions. Python has them, Ruby doesn’t. This still burns me. I blame Haskell for getting me addicted.

People tend to focus on little details like whitespace sensitivity when they complain about Python. Especially Rubyists — we tend to look on strict, seemingly “arbitrary” rules with a jaundiced eye — but this is a red herring in my opinion. A good developer is going to indent correctly and consistently anyway. If you don’t have a standard way of indenting your code— or if, God forfend, you use tabs— someone should shake the crap out of you.

But… I’m sorry, I love my end keyword. Lose it, and if you have to re-indent code manually it’s a serious pain in the ass. The fluttering, anchor-less statements of Python rely on a single colon to indicate an upcoming indentation, and that’s not enough for my poor eyes (I like a nice sturdy end to indicate the end of an indentation). It is a bit nice to lose an extra line every time, but I’ll happily refer to it as the Clarity Tax. Obviously this is a personal preference.

I love my blocks; the stunted lambda Python supports seems a pittance. I do think the new with keyword is an interesting approach towards “cleanup blocks” (eg, File.open), though they feel a bit like hidden magic and a bit hackish to implement. I know, I know, a Rubyist complaining about magic!

Stating what I think about explicit returns would be too explicit for this blog.

Python doesn’t feel “fluent” to me— in terms of flow, it’s the stuttering Tarzan of programming languages— staccato phrases, prolific underscores, colons and parenthesis galore. Granted, this is a matter of taste (and I happily code in Erlang, which is far worse), and it is a programming language, but I would consider Python far more functional (in the utility sense) than elegant.

Multiple inheritance is still more of a pain than it’s worth, super() is pretty lame, and the fact self still needs to be a parameter in method definitions makes me scratch my head in befuddlement.

Python threads are far better than Ruby 1.8 threads, plain and simple. They’re strict (you ask them politely to exit, on their own time) and competent.

setuptools is kind of cool, and eggs are also neat; Rubygems seems simpler and more cohesive, however.

Frankly, properties and generators are still a bit missing in my education; they’re not features that “pop out” or seem to be explained in clear terms. This is probably my failing, and may have prevented me from seeing Python in a clear light in some cases.

The Python executable being a REPL is just plain awesome. I still don’t know why IRB is separate from the Ruby executable (and don’t even try to read it, it’s a shark attack). My good friend David Black, even older Ruby salt than I, commiserated on this recently.

So, I think that’s enough for now. I’ve also been playing with Django a fair bit, so I may post something on it soon.

Updates

I’ve removed my previous statement on Pythonistas not finding closures useful, as it was confusing and seemed to indicate a lack of support in the language rather than discussions I’ve had with Python developers on their utility in day-to-day development. I’m aware Ruby developers complaining about missing language feature X in Python is probably as annoying as Python developers complaining about VM speed in Ruby, and based on just as outdated information. Python’s “lack of closures” is a common straw man, and I apologize for the confusion.

There seems to be a lot of contention on the tabs vs spaces comment. It’s a personal view, largely based on code portability (including copy and paste to a browser) and modern editors. Lots of people on either side of this issue; feel free to debate amongst yourselves.

I wasn’t overstating the fact Ruby developers complain about Python’s importance of whitespace. It’s often one of the first criticisms leveled against the language (and as I indicate above, a fairly petty one), and is easy to find on the web via google.

To add something else that I think is awesome about Python: docstrings. In comparison, Ruby’s tools-only approach (ie ri for retrieval and rdoc for generation) is pretty weak. It’s amazingly handy to access documentation via the console; wouldn’t it be neat if we could do something like the following in Ruby? It would make building new documentation tools (not to mention casual investigation) so much easier.

puts some_object.documentation # or `doc` or `__doc__`, etc

# For methods
puts some_object.method(:method_name).documentation

A note for commenters: whenever possible, please include code or references. I’m quite happy to own up to and add an update here if I’m wrong on a point, but I’d like references available for readers, especially if it’s a common misconception.

Discussion