Eckel's article is getting pretty long in the tooth at this point -- I
remember reading it back when I was a Python user several years ago,
and it actually delayed my swith to Ruby for a few months, at least. I
probably don't qualify as a Python expert, but after being exposed to
both for non-trivial projects, there are definitely some differences
that make me prefer Ruby.
First, because all object "slots" in Python are public, (stupid
conventions like underscore prefixes aside) you see a lot of code like
this:
obj.setFoo("bar")
This is because 'obj.foo = "bar"' is a direct assignment, with no
method call involved. Since that's an encapsulation no-no, you get a
bunch of long-winded setFoo and getFoo methods all over the place,
which gives me nasty flashbacks to my days writing Java code. (Note:
this is probably getting better now with the standard decorator syntax
making automatic slot wrapper code generator more acceptable in the
Python world.)
Second, the crippled 'lambda' form (you can't include multiple
statements, since Python imposes its fugly statement/expression
separation) means you either a) give up on some very elegant potential
uses of first-order functions, or b) pollute your namespace with a
bunch of throw-away definitions that should be anonymous. Blocks and
proc/lamba objects feel more expressive, at the cost of having to use
the #call or #[] methods to actually invoke them.
Also, while I'm less than proud to admit it, a few of the "Perl-isms"
in Ruby, such as the =~ operator, simply seem more natural to me than
their Python equivalents. I try to avoid using the special syntax and
"magic" globals like $1, $2, et. al., but having spent so much time
wearing a sysadmin hat, (and we all know that means reading and hacking
on Perl code) it's nice to just be able to toss out regexp-based
one-liners when the urge/need arises.
Finally, metaprogramming in Ruby has always been a more straightforward
and common practice than in Python. The combination of
{class,module,instance}_eval, blocks, symbols (as a compact
representation of method and attribute names), and import/subclass
callbacks just makes more sense, IMHO, than metaclasses and multiple
inheritance, which are more or less essential for idiomatic Python
metaprogramming.
I do miss a few things: most importantly, list comprehensions, and
imported modules simply being another object/namespace to be used with
normal dot-notation. Python has also had a clean syntax for keyword
arguments in method calls for some time, and while I'm pretty
comfortable with the implicit hash-conversion model, it still feels
hacking compared to real kwargs.
Regardless, I agree with the folks earlier in the thread who've said
that you should pick the language that fits your brain better. For
recovering Java programmers, that may well be Python, as the heavy use
of inheritance and explicit setters and getters won't require any major
shift in design practices. On the other hand, if you're coming from
Perl, or maybe even C++, where the style is more fluid, Ruby will
probably feel more efficient, since you end up writing less boilerplate
code, and using a flatter class hierarchy.
-Lennon