seeking deeper (language theory) reason behind Python design choice

Python python at bladeshadow.org
Tue May 8 23:48:52 EDT 2018


On Tue, May 08, 2018 at 12:45:29AM +0000, Steven D'Aprano wrote:
> Currently, the real reason is that lambda expressions are limited to a 
> single expression as the body of the function, and binding operations in 
> Python are statements. 

...which begs the question, why shouldn't assignments be expressions,
as they are in many other languages?  TBH this is one of the few
things about Python that I dislike.

> > So far, no satisfying answer has come up, except for maybe to avoid a
> > programmer accidentally typing `=` instead of `==`, which I find a bit
> > unsatisfying as the only reason.
> 
> No, that's the reason why = is a statement not an expression. That's not 
> why statements aren't allowed in lambdas. If we had blocks, this would be 
> perfectly acceptable:
> 
> lambda arg: %%%START BLOCK
>     spam = arg + 1
>     ...
>     %%%END BLOCK
> 
> since = in a statement on its own is not dangerous. People *almost never* 
> intend to write == for the side-effects only:

Seriously?  I do this--not every day, but more than occasionally, not
just in Python.

    flag = (spam == arg)
vs.
    if spam == arg:
        flag = True
    else:
        flag = False
    if flag:
        do_something()
    else:
        do_something_else()

Obviously this is a simple example which could be rewritten and/or the
comparison copy-pasted; assume a more complex system where you need to
check if the two objects were equal in multiple places, but obtaining
the objects is computationally expensive (say, processing a large file
to obtain a large list of objects), and comparing them is likewise
computationally expensive.

>     # don't care whether they are actually equal or not
>     # just want to call the __eq__ method for its side-effects
>     spam == arg + 1
> 
> Since that never happens in real life, there's no risk of accidentally 
> writing "spam = arg + 1" when you wanted "spam == arg + 1".

I've always felt that this mentality was insulting to the programmer:
"You're too stupid to get this right."  Sure, I've created that bug in
other languages (or rather its inverse) but not since college.  You
make it a few times, you go nuts debugging it, you learn what it is,
you never do it again.

And, this kind of thing is what code reviews are for--Python isn't so
idiot-proof that you can get away without doing them for any
non-trivial code--so (IMO) the language should not prevent you from
doing useful things *simply* because you *might* make a mistake.  I'll
give you an example that is both a case where Python's design choices
make creating a bug easier, AND a case where allowing assignments to
be expressions would save you.

    flag = we_are_done()
    while not flag:
        # do some stuff
        ...
        if error_occured():
            break
        falg = we_are_done()
    notify_user()
   # flag will be checked again later, perhaps for error reporting

Here, a common programming pattern (prime the loop control variable)
gets you in trouble, because the assignment happens in two places, and
you mistyped one of them.  There's no syntax error, but your program
will execute forever, unless you were already done on the first call
to prime the flag, or an error occurs.  This is probably worse than
the = vs. == error, because your brain tends to "autocorrect" certain
kinds of spelling errors, whereas experienced programmers learn to
look for (or avoid entirely) the assignment vs. comparison bug.  The
error here is reasonably easy to spot, given the trivial nature of the
example, but would likely be harder to spot in more complex code with
longer, more meaningful variable names.

This example also is a case FOR allowing assignments to be
expressions.  If Python allowed them, you could rewrite this as:

   while not (flag = we_are_done()):
        ...
        if error_occured():
            break
   notify_user()
   # flag will be checked again later, perhaps for error reporting

This COMPLETELY PREVENTS the spelling bug in the code above, since the
assignment only happens in one place; and as a bonus it's less code.




More information about the Python-list mailing list