Critique of the changes in Python 3

The “experts” are wont to wax long about the beauty of Python as an elegant programming language, whose clean design leads to better code and eliminates many careless errors. Python by many is considered more than just a digital tool, but rather is kind of art for programmers—a form of striving for stylistic perfection in code practiced with the same relish that artists apply to their work. The relentless efforts by Guido van Rossum and his cohorts to rework the rough edges in Python is like watching Michelangelo attempting to smooth away the last mars on David’s torso. The artist is never quite satisfied with his masterpiece and keeps insisting that it is not quite perfect, while the rest of the world pauses in befuddlement looking for the “blemishes”.

My recent efforts to learn Python leave me scratching my head in a like manner, as I try for the life of me to understand why it was so necessary for the Python developers to rip up version 2 of their masterpiece and introduce an incompatible version 3. Most designers of computer languages bend over backwards to maintain backward compatibility, especially if their language is widely employed, but not the Python developers in the pursuit of stylistic nirvana. When I think about the tens of thousands of vital scripts to maintain servers, run desktop applications and power web pages, my heat aches thinking about the tremendous cost of migrating all that code to the incompatible Python 3.0.

Still, I felt certain when I started reading the documentation that there must have been some compelling reason why the next version of Python had to be made incompatible with the millions of lines of existing Python code. After all, having an incompatible new version means that the developers will have to maintain two versions of the language for quite a few years in the future—both the old version for the thousands of scripts which haven’t been rewritten and the new version for all the new code and the recently migrated code. It means a tremendous amount of ill-will and confusion as all the extra libraries go through an ugly period of transition and testing to work with the new version.

Plus, it is a tremendous waste of storage space and extra downloading, because almost every user of Python programs will have to install two versions of python on their computer. That might not be too large of a burden for typical desktop computer, but for many mobile devices where space is at a premium, it can mean that one version doesn’t get included so a lot of useful applications simply won’t run. I wonder how the programmers of Sugar—the operating system of the OLPC laptops—are going to feel about cramming a second version of python into their already crammed harddrives. Plus, two versions means more time and bandwidth wasted downloading Python. This may seem like a minor point if you are one of the fortunate few on the planet who has broadband access 24 hours a day, but the vast majority of the world can only obtain Python by going to a cybercafe and downloading it patently at a couple kilobits per second. Discovering that you downloaded the wrong version of Python doesn’t mean a another couple clicks to download the right version, it means making another tiresome trip to the nearest cybercafe and paying more money to sit in a little booth and drum your fingers while the download creeps along.

Given all the trouble that a new incompatible version of Python will cause in the world, I was shocked to discover that Python 3.0 largely offered nothing which Python 2 couldn’t do. There was no compelling new functionality which justified ripping up the language and starting over. Instead, all the changes were largely stylistic. In other words, the language incompatibility was predicated on pursuit of aesthetics, a change which seems perfectly reasonable for the rarefied sensibilities of Python’s designers, yet leaves the rest of the world scratching it’s head either in bemusement or downright irritation at the hassle. But, maybe it should be expected for a language which has self-consciously coined its own adjective “Pythonic” to describe its particular style of coding and has even inspired its own poetry to describe that style aptly entitled “The Zen of Python.”

None of the desired changes really required ripping up version 2 of the language in my obviously unenlightened opinion, as the developers have aptly demonstrated by backporting most of the changes from version 3.0 to version 2.6. Unfortunately Guido and crew weren’t content to let their masterpiece contain unaesthetic “deprecated” elements and allow both an “old style” and “new style” of coding to happily coexist in their perfect language. That would mar their artistic masterpiece, so they are now forcing everyone to adopt the new aesthetic.

In a few cases, the new artistry has some practical benefits, such as the new keyword with, which will cut down on the hassle of writing out complicated try and except clauses. In most cases, however, version 3 is simply a bother for the Philistine programmer who just wants to get a task done and done care a whit for maintaining a holistic style. Most Python programmers will not welcome having to remember to put parenthesis around every print statement. If the designers wanted to allow the unwashed masses the ability to redefine print at will, they could have implemented it without parenthesis, but their aesthetic requires that if print behaves like a normal redefinable function it should contain parenthesis even if a generation of Python programmers have grown accustomed to not using them. Remembering to add () every time you want to output anything anything is minor cosmetics compared to remember to change all those loops which are the hallmark of Pythonic quintessence from   for x in y:   to   for y as x:   The aesthete in Guido just couldn’t bear to see in being used in such a profane manner as   for x in y in z: , so he had to redefine   in   as   as   so it wouldn’t ever be confused with in, even in rare cases.

Of course the greatest hassle for the quick and dirty Python programmer is Guido’s insistence that succinct C-style print statements be expunged for the more verbose Pythonic ones, so all programmers will know in their bones that they are proper objects and treat them as such. The good old % which used to be the hallmark of Pythonic pithiness as a way to insert variables in a string has been expurgated as the dirty hack which it was and replaced by a verbose format() object method. Nobody will deny that C-style formatting of strings was complicated and error-prone, but it is a convention well known by every programmer worth his/her salt for the last 4 decades and employed in the mostly widely deployed languages such as C, C++, C#, Java, PHP, and until recently in Python. It is considered a rite of passage for every good programmer to learn that odd combination of characters such as   %+5.3d   which will insert a properly formatted variable in a string. The arbiters of Pythonic style weren’t content to simply introduce a clearer alternative syntax for inserting variables in strings, but still allow the obstinate masses to go on using their dirty C-style conventions if they so liked as PHP has done. No, this pragmatic, backward compatible solution would contravene the first rule of Python’s Zen: “There will be one style and only one style”.

One of the first rules of good programming is to break code into lines of 80 characters or less so it is readily readable and multiple windows of code can sit side by side on the screen to allow for easy comparison and copying of code between programs. Unfortunately the new format() method for strings doesn’t leave a logical place to easily break up a print statement into multiple lines as the old % operator allowed:

print "Now every programmer must change their %s | %s | %s." %
   ("strings", "coding style", "aesthetic")
print ("Now every programmer must change their {0} | {1} | {2}.".format(
   "strings", "coding style", "aesthetic"))

Because there can be no whitespace allowed between the end of the string, the dot operator, and the method function name, there is no good point to add a line break in between "...".format(...) . Either the string itself gets broken up on multiple lines or the parameters to the format method get placed on a separate line from the opening parenthesis of the function as shown in the example above. Plus, the programmer has to remember to properly number all the variables, which can easily introduce its own errors in long print statements where it is hard to keep track of all the numbers. Of course, a Pythonic guru would advise using identifiers rather than numbers, which makes the code even more verbose and even more of a hassle when the goal is to just write a quick script rather than spend creative time creating more variable names.

print ("Now every programmer must change their {element} | {description} | {art}.".format(
   element = "strings", description = "coding style", art = "aesthetic"))

To add insult to injury, the quick and dirty programmer will probably forget to add two closing parentheses to terminate every print statement and thus introduce additional errors in the code. (Plus, the new syntax for print statements and string formating seems to violates Python’s own cardinal rule to avoid unnecessary parentheses and brackets whenever possible, but the developers of Python should not be questioned in what is properly Pythonic style.)

Advocates of Python often wonder why so many seemingly intelligent programmers would choose a ramshackle mess of a language like PHP, which was haphazardly cobbled together by dozens of different architects who clearly weren’t sharing the same blueprints. They borrowed Perl-style regular expressions and C-style libraries and threw them into the pot with no regard for proper name conventions or a holistic style. Python’s partisans turn up their noses when regarding the linguistic messiness of Perl which like a human language sports multiple manners of expressing the same thing. They reject the archaic verboseness of Ruby syntax whose begin and end keywords are reminiscent of hoary, old Pascal which they suffered during their boring Programming 101 classes as freshmen in college.

What Python’s partisans don’t get, however, is that these other scripting languages may not be as stylistically refined or as clean in design, but they do not introduce new styles that force the programmers to rewrite all their code.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s