Python vs. Perl, which is better to learn?

Alex Martelli aleax at aleax.it
Fri May 3 12:02:24 EDT 2002


Jason Voegele wrote:
        ...
> On the other hand, the ability to call functions without parentheses
> is not so clear-cut.  Some believe that it leads to less readable
> code.  Others (such as myself) view it as essential for supporting the
> Uniform Access Principle.  Usually I'll leave the parentheses off of a

"Properties" do UAP better, and meanwhile you get uniformity at ANOTHER
level: all methods are also attributes and you can deal with them as
you deal with other attributes.

In other words, in a language that lets you access object attributes
directly (except when properties are interposed, etc), parenthesis-less
function calls may be seen as _damaging_ uniformity:
        x = y.z
if y.z is a 'real' attribute, bind its value to z; but if y.z is a
callable attribute (method), then DON'T bind the attribute to z, but
rather implicitly and invisibly CALL it and bind the RESULT to x.

You may not like the uniformity between callable and non-callable
attributes, but personally I find it one of Python's strengths.

As an analogy, consider assignment in VB6:

        x = y

(x and/or y might be composite names, and you may optionally use a
LET verb before x, though nobody ever did:-).

In VB6, this means: if x is a normal thing, assign to x; but if x
is a special object, then assign to the *default property* of x
instead, i.e., actually do (e.g.) x.value = y -- and similarly for
y, it's used directly if "a normal thing", but if "a special
object", then the "default property" is used instead.  So depending
on the nature of x and y this might actually be doing (assuming
the default property is named 'value', popular but not mandatory):
        x = y
        x.value = y
        x = y.value
        x.value = y.value
When you wanted to REALLY TRULY do x = y for special objects, you
then had to code explicitly:
        SET x = y
(which would then give error unless x and y ARE special objects,
but that's another wart yet:-).

I've long considered it one of the worst warts of VB, and surely
one which most confused VB beginners (even ones with some good
experience in other languages) -- whenever called upon to help
find a bug I always looked first for missing SET verbs and often
found one.

Apparently Microsoft agreed, since in the move to VB7 (aka VB.NET)
they took the opportunity to make lots of incompatible changes to
the language -- including removing this misguided application of the
ideas of polymorphism and uniformity.


Having to know whether x.y is callable or not before I'm able to
store [a reference to] the attribute itself somewhere, IMHO, makes
callable attributes less than first class citizens and thus in
a way breaks uniformity.


In my experience, 9 times out of 10 I can afford to just let client
code get at an attribute -- and 10% of the time I want this to be
("trigger", if you will) a function call instead.  It's higher for
_setting_ of attributes -- maybe as high as 30%.  Still, in many
cases I don't need functions to be called.  This is borne out by a
non-systematic observation of Java getThis, setThat methods -- it
seems to me that a vast majority of cases sees these methods as
boilerplate just copying some piece of data in or out, no more.

Old Python's ("classic object model") lets you "build" properties
out of special methods __getattr__ and __setattr__ -- not too bad,
though not maximally elegant (particularly because if you define
__setattr__ you must then bypass it carefully for *internal* cases
of access -- __getattr__ has no such problems).  2.2's "new object
model" adds Properties as (IMHO) one of its most significant
features (head to head with subclassing builtin types -- which,
admittedly, Ruby always had:-).  For those 10% or 30% or whatever
of cases where I need methodcalls triggered upon attribute get
and/or set, I THEN write accessor methods (I found it most easy
and useful to name them getThis, setThat -- Java conventions) and
group them into a property with an assignment in class-scope
        prop = property(getProp, setProp)

Now, and now only, will accessing x.prop or setting x.prop=23
call x.getProp and x.setProp as appropriate.  __getattr__ is now
needed only for rather special uses (works great for 'blind
aggregation/delegation' for example -- since methods are gotten
just like any other attribute).


> method call if it takes no arguments, which allows me to switch
> between using a variable and using a method more easily.  I also find
> it easier to read in such cases.  I find empty parentheses() as you
> find in C++, Java, and Python rather ugly (a "call" statement in
> disguise, as it were), although at least in Python and C++ they are
> actually an overridable operator, whereas in Java they are just
> gratuitous syntax.

Yes, you can't take a reference to a method in Java (while you can
in Python, and also, sort of, in C++, though it's a "method
pointer" there, and rather unwieldy).  Calling is indeed an OPERATOR,
while the lack of operator means "a reference to this thingy over
here".  Now THAT is uniformity: naming something always gets a
reference to that thing -- if and when you want to DO something
with that reference, you express that "something".  Properties let
you control the 'dot-operator' selectively and with very fine grain.


> In addition, I'll leave the parentheses off of function calls that are
> conceptually similar to keywords.  For example, Ruby's "raise" method
> (which raises an exception), or an "assert" method from a testing
> framework, or attr_accessor and friends.

Given that raise and assert are statements in Python (Ruby is more
flexible by having them as methods, though Python's design choice
has its own little pluses too -- interesting tradeoffs), I can hardly
criticize you for "wanting" them to be in Ruby too:-).


Actually, it's when a callable HAS arguments that it may be least
disruptive to allow it to be called without parentheses, just by
"juxtaposition" to its arguments.  I do admit I love Haskell's
way of expressing "f a b c", so clean -- no noisy parentheses nor
commas for the typical case.  Of course, it DOES require the
"implicit currying" concept, so that e.g. f a may return a function
that then takes b and returns a function that ... -- delightful,
but perhaps not all that applicable unless the compiler has some
strong information about what callable takes what arguments:-).

For a compiler lacking such knowledge, I opine that unformly
mandatory parentheses as "call-operator" is probably simplest
and thus preferable -- though I sympathize with the drive to
avoid "useless pixels on the screen" (one habit I truly detest
is putting wholly unneeded parentheses around the value[s] in
a return statement -- some do that in C, too -- or, in Python,
around the condition in an if or while... *eeech*...).

One day I'd really love to co-author a *balanced* comparison
of Python's and Ruby's pluses and minuses -- "co-author" 'cause
I'd need to find a partner in crime who admires Python but
still prefers Ruby, just as I admire Ruby but still prefer
Python -- and one "into" Ruby's triviae and minutiae as well
as overall philosophy as much as I'm "into" Python's.  Oh well, one day...


Alex




More information about the Python-list mailing list