"sins" (aka, acknowledged language problems)

Alex Martelli Alex.Martelli at think3.com
Fri Dec 17 04:20:46 EST 1999


Tim Peters is kind enough to respond to my request
for an URL about acknowledged Python defects with
detailed considerations boiling down to:

	lots of tiny pet peeves, but no consensus

which seems to be a very accurate assessment.


So, maybe I can move down a notch and try fishing
for Python things which at least "annoy" a "vast"
(carefully vague term:-) number of Pythonistas,
without compensating advantages to "many" others.

E.g., "lack of full GC", since it can be rephrased as
"with care, you can control where and when your
objects are finalized", would not qualify!-)


The type/class split has been mentioned (it does
not affect most people, it helps none, it hinders,
albeit slightly, most of those who are trying to
do certain advanced things).


Would this also apply, to a weaker but broader
extent, to the lack of assigning-operators, an
"expression" kind of assignment, increment and
decrement in particolar, or other issues of the 
expression/statement split?

E.g., I would like to offer for comment a typical
"Python-newbie" kind of personal anecdote.
(Entering this from memory, so please excuse
any typos that might happen)...:


I (think I) need a simple "template" sort of
operation whereby an input stream (mostly a
file) is copied to an output (ditto), with some
kind of "substitution" happening on the fly, and
a reasonable amount of generality.  There is
sure to be something around, but, hey, I'm a
newbie, I need to learn, so yesterday evening
I decide to design my own -- looks like trying to
implement it may make for a nice weekend kind
of project.  Starting from a newbie's vague
acquaintance with Python facilities, I reason...:

Let's see -- basically I want line by line copying
of an input "template" stream, to an output one,
while some variables get substituted.  But why
just variables -- let's make it expressions -- the
"eval" builtin should make those just as easy, I
think.  But how do I demarcate the expressions,
any given syntax I might choose would surely
be awkward for some uses.  Hmm, regular
expressions should help -- the caller will pass
me a re, and the first parenthesized group in
it will be the expression to eval, with which the
re itself will be substituted -- neat.  Of course,
I'll also need a dictionary for the eval itself.

I may need a class, but let's first see if I can
make it a function -- and I fire up IDLE and
start editing smartcopy.py, after a long doc
string detailing the above design, with...:

import sys

def copy(regex, dict, inp=sys.stdin, oup=sys.stdout):

Now, I need to loop: read a line, check if it
matches the regular-expression arg, and
if so then do fancy things, finally output it.
Darn, this needs that goofy idiom...:

    while 1:
        line = inp.readline()
        if not line:
            break
        if regex.search(line):
            pass # we'll fill this in later
        oup.write(line)

I add the "if __name__=='__main__'" idiom and
test it as a straight copy-through... ok.  Now,
for the 'meat' of the substitution... I look at the
re module's documentation, and the doc for
"sub" stares at me... "repl" can be a FUNCTION!?

Wow... I add a first couple of line before the while:

    def repl(match,dict=dict):
        return eval(match.group(1),dict)

and change the if/pass couplet and the write
call to the single line:
        oup.write(regex.sub(repl,line))

That's *IT*?  I can't believe it... yep, a little
test convinces me, that it actually is.  The
"weekend project" turned into 15 minutes.
My girlfriend, busy at her email on another
computer, smiles indulgently at my childing
enthusiasm at the result.

And YET... human nature being what it is...
I cannot help but keep staring at the result:

import sys

def copy(regex, dict, inp=sys.stdin, oup=sys.stdout):
    def repl(match,dict=dict):
        return eval(match.group(1),dict)
    while 1:
        line = inp.readline()
        if not line:
            break
        oup.write(regex.sub(repl,line))

and wonder that *FOUR*-count-em lines of
this function, fully half of it, are devoted to
the trivial, frequent, repetitive task of looping
over input lines, reading each one, bailing
out when done.  Yeah, I know I could have
written the break on the same line as the
if, but that's considered bad Python style:_)

But why can't I change those 4 lines to, say:
    while line := inp.readline():
using the suggested ":=" operator that I've
seen mentioned now and then?  Or, maybe
even better, "while line from inp.readline()"
or other variants suggested in the past.

Apparently, I can't because "upper-crust"
Pythonistas like the "while 1:/...break" style --
or at least, that's how a newbie like me can
easily interpret the existing discussion.

And yet, here, this idiom would rebalance
the relative 'weight' of different parts of
this tiny but useful function.  I know I
could write, for this specific case:
    for line in inp.readlines():
with similar overall effect, but why should
I change semantics to "read everything
at once", when line-at-a-time is what is
really needed, just to get neater syntax?


OK, OK, this is no doubt the kind of thing
that can be classified as a very pet peeve,
rather than as a "deadly sin"!-).

And yet, what else can you expect when a
language lets a newbie develop in 15 minutes
a task that by rights should take quite a few
hours...?  With too much time on his hands,
the newbie is sure to find something to
grouch about!-)

Another way to put it -- when a language
manages to combine expressiveness, clarity,
concision, and power, to the extent that
Python exhibits even in a newbie's hands
on an example such as these, such warts
as having to take 4 lines for such a very
common idiom may stand out sharply by
contrast, particularly since single-line
idioms for this sort of thing are so common
in languages otherwise far less powerful,
AND since Python itself would easily allow
a single-line idiom if the semantics was
a slightly different one of roughly similar
frequency.


If I can get some balanced discussion about
this, and perhaps similar problems, maybe I
can put together a suitable page myself.

Maybe call it "controversial booboos" rather
than "deadly sins":-).  If a "prospect" should
see that THIS kind of minor issues is the
worst that Python users have to complain
about, and compare and contrast this picture
with the famous "deadly sins", then maybe
this could exert quite a draw:-).


Alex-the-Python-newbie





More information about the Python-list mailing list