As some of you may know, I’m a huge perl person. I’ve written a lot of it, and I know it very well. That’s not to say there aren’t people who know it better than I do, but I know it well.
Now, while I’m a big Perl fan, it’s worth noting I’m well aware of Perl’s flaws: a poor OO model, poor (or some might argue non-existent) exception handling, and some very dangerous implicitness to name a few.
So, recently, I decided to give both Ruby and Python a shot. Now, I’ve looked at python a few times – but the whole whitespace-means-stuff thing really turned me off. Explicit blocking is a good thing. As such, I never really looked far enough past that to give it a fair chance. So I decided it was time to give python a fair shot.
After playing with it for a while and writing a few small scripts and then rewriting them, I found the following really disheartening things. But just to make sure I wasn’t just expecting python to act like Perl, I ran them by a friend of mine who’s a big python guy, and he admitted not being thrilled with these aspects of the language either.
So here you are – a day in Python from a Perl guy.
The string’s split function uses regexes but doesn’t support them
If I have a string object and I call it’s split() method with no argument, it automatically splits on the regex \s+. However, the method only takes strings as parameters. Which means you can’t even pass in \s+ as an argument. OK, well you can, but only if you want to match the literal string ‘\s+’. So, this code:
foo = 'b a r' print foo.split()
returns the expected 3-element array ['b', 'a', 'r'], but this code:
foo = 'b a r'
print foo.split('\s+')
returns the single-element array ['b a r']. Doing foo.split(/\s+/) as a ruby-coder might try is a syntax error and foo.split(\s+) is as well. But alas, we look through python.org/docs to find – aha! there’s a regex class! Sadly, you cannot pass a regex object to string’s split() method. This code’s last line is a syntax error:
import re
p = re.compile('\s+')
foo = 'b a r'
print foo.split(p)
I get, TypeError: expected a character buffer object. The way to actually do this is completely counter-intuitive, you can’t use the string’s split() method, you must use the regex’s split() method, and pass the string in:
import re
p = re.compile('\s+')
foo = 'b a r'
print p.split(foo)
This code will return the desired 3-element array ['b', 'a', 'r']. So, why wouldn’t the string function do a type-check on it’s parameter so you can pass in a regex object?
Or better yet, why can’t the re class extend or overload the string class’s split() method to type-check and use its own method if it’s a regex or the original method if its a string? There’s several ways to make this intuitive or consistent, but none of them appear to be implemented as far as I can tell.
What happened to constructors?
Speaking of regexes, it seems cumbersome to require the programmer to call the compile() method when creating a regex object. When instantiating a regex object, clearly I want to make a regex, so why doesn’t the constructor take the string and “compile” the regex? It’s not clear to me that this concept even exists in python. That would be a shame.
I am OO, I’m not OO, I am OO, I’m not OO…
Python touts itself has having done OO better than Perl (this isn’t hard), and as being an OO language at its core instead of as a bolt-on. So if I have a string that contains simply an integer, one would expect some method to get an int object out of it. For example, if I have foo = "1" and want to do a mathematical operation on it (add 4 and get 5 as a result), one would expect something like foo.int() or foo.atoi() or foo.toint() to exist. Instead there are global functions. Global functions? In an object-oriented language? Yup, this is the code you’d be looking for:
foo = "1" bar = int(foo) print bar + 5
A global function to cast to another type. Yeah, that’s OO. By the way, there’s no OO method for doing addition either (while I find those ugly, it would at least be consistent). There’s objects and types and global functions and in most cases things are objects, but not in others. This is a Perl problem Python was trying to get away from.
Poor interpreter errors
One of the great things about interpreted languages is that an interpreter is around at run-time and as such, has more data and can hopefully provide better error messages. There are far less of those fun cryptic compiler and linker errors. So, I’d expect python to be able to tell me something simple like “you forgot to declare a variable.” Take this code:
for x in range(10): hash['foo'] = 'bar'
Not very useful code, but easy enough to read. There’s a problem though – I haven’t declared the dictionary (that’s a hash or an associative array for those of you not familiar with python nomenclature) variable hash when I attempt to assign to its foo index. But instead python tells me I have a type mis-match:
Traceback (most recent call last): File "<stdin>", line 2, in ? TypeError: object does not support item assignment
That’s not a type error; that’s an undeclared variable! This code works fine:
hash = {}
for x in range(10):
hash['foo'] = 'bar'
It’s perfectly reasonable to require variables be declared, but then your interpreter should be able to error when they’re not!
None of these are show-stopping. None of them are evil. But it’s a large number of fairly annoying things to hit within your first half-hour with a language and not find some really good explanation within the first day. No language is perfect; and Python seems to have a lot of strengths. I’m continuing to play with it and with Ruby; we’ll see how it goes.

I second your opinion – I’m also a Perl fan, and I have to learn Python, since lot’s of useful libraries are in Python. And Python is sort of nice, but…. so many ad hoc entities – exactly “I’m OO, I’m not OO, I’m OO ….” loop