Velocity Reviews > if/elif chain with assignment expressions

# if/elif chain with assignment expressions

Paul Rubin
Guest
Posts: n/a

 07-11-2004
Sometimes you want to compute an expression, then do something with
the value if it meets a certain criterion; otherwise, try a different
expression (and maybe different criterion) instead, etc. With := as
an assignment expression operator, you could write:

if (y := f(x)) < 5:
fred(y)
elif (y := g(x)) < 7:
ted(y)
elif (y := h(x)) < 9:
ned(y)
etc.

Of course there are alternative ways of doing the same thing, but they
all seem to be messier.

steve holden
Guest
Posts: n/a

 07-11-2004
Paul Rubin wrote:
> Sometimes you want to compute an expression, then do something with
> the value if it meets a certain criterion; otherwise, try a different
> expression (and maybe different criterion) instead, etc. With := as
> an assignment expression operator, you could write:
>
> if (y := f(x)) < 5:
> fred(y)
> elif (y := g(x)) < 7:
> ted(y)
> elif (y := h(x)) < 9:
> ned(y)
> etc.
>
> Of course there are alternative ways of doing the same thing, but they
> all seem to be messier.

Indeed, you might think so. But this topic has been discussed
exhaustively (which isn't to say you aren't about to hear a lot more
about the subject) in this group, and the assignment operation is *not*
an operator for specific reasons the FAQ attempts to make clear in
http://www.python.org/doc/faq/genera...-an-expression

regards
Steve

steve holden
Guest
Posts: n/a

 07-11-2004
Paul Rubin wrote:
> Sometimes you want to compute an expression, then do something with
> the value if it meets a certain criterion; otherwise, try a different
> expression (and maybe different criterion) instead, etc. With := as
> an assignment expression operator, you could write:
>
> if (y := f(x)) < 5:
> fred(y)
> elif (y := g(x)) < 7:
> ted(y)
> elif (y := h(x)) < 9:
> ned(y)
> etc.
>
> Of course there are alternative ways of doing the same thing, but they
> all seem to be messier.

Indeed, you might think so. But this topic has been discussed
exhaustively (which isn't to say you aren't about to hear a lot more
about the subject) in this group, and the assignment operation is *not*
an operator for specific reasons the FAQ attempts to make clear in
http://www.python.org/doc/faq/genera...-an-expression

regards
Steve

Paul Rubin
Guest
Posts: n/a

 07-11-2004
steve holden <(E-Mail Removed)> writes:
> Indeed, you might think so. But this topic has been discussed
> exhaustively (which isn't to say you aren't about to hear a lot more
> about the subject) in this group, and the assignment operation is
> *not* an operator for specific reasons the FAQ attempts to make clear
> in
> http://www.python.org/doc/faq/genera...-an-expression

Yeah, I've seen those discussions before. The if/elif/elif example was
something I hadn't seen in those discussions, and it came up in some
code I was writing yesterday, so I posted about it.

Fernando Perez
Guest
Posts: n/a

 07-11-2004
Paul Rubin wrote:

> steve holden <(E-Mail Removed)> writes:
>> Indeed, you might think so. But this topic has been discussed
>> exhaustively (which isn't to say you aren't about to hear a lot more
>> about the subject) in this group, and the assignment operation is
>> *not* an operator for specific reasons the FAQ attempts to make clear
>> in
>>

http://www.python.org/doc/faq/genera...-an-expression
>
> Yeah, I've seen those discussions before. The if/elif/elif example was
> something I hadn't seen in those discussions, and it came up in some
> code I was writing yesterday, so I posted about it.

And your example is an excellent argument, IMHO, of why the current situation is
bad. While the usage cases in the faq have easy alternatives (iterators), your
example does not, and you do end up forced to write a bunch of unnecessarily
verbose code. In general I applaud python's efforts for being clear, readable,
and not error-prone. But this is one of those cases where leaving the training
wheels on causes genuine grief (I have in the past many times run into the
example you mentioned, and have cursed it silently).

I very much doubt this will change in the language, but we can always hope

Cheers,

f

John Roth
Guest
Posts: n/a

 07-11-2004

"Paul Rubin" <http://(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> steve holden <(E-Mail Removed)> writes:
> > Indeed, you might think so. But this topic has been discussed
> > exhaustively (which isn't to say you aren't about to hear a lot more
> > about the subject) in this group, and the assignment operation is
> > *not* an operator for specific reasons the FAQ attempts to make clear
> > in
> >

http://www.python.org/doc/faq/genera...-an-expression
>
> Yeah, I've seen those discussions before. The if/elif/elif example was
> something I hadn't seen in those discussions, and it came up in some
> code I was writing yesterday, so I posted about it.

I thoroughly agree. I've come up with that any number
of times, and allowing an assignment in an expression
is one of the things that I think should be done.

Note that I don't really care about the syntax, and
I care even less if it's really intuitive to novices. It's
one of those things that leads to simpler, more expressive
code when you need it, but it's not something that's
absolutely necessary to hack together a working
program while you're learning the language.

The use case is an expression in an if statement, not
an expression in a while statement. The latter can
be handled with an iterator and a for statement,
which might be a good idea, and it might not depending
on the specific situation.

There is an alternative, which is to find all of the
cases where this is likely to be a problem, and fix
the calls so that they naturally return an iterator.

To make this specific, let's take a look at the
<string>.find and <string>.rfind. This method
pair is probably the poster child of how not to
do it in a pythonic manner.

Let's assume we had a <string>.findall()
method, defined to return a list of all
indexes of the first character of each
substring that matches the given string.

Then we could say something like:

for firstMatch in myString.findall("fubar")[:1]:
do something with it

While this is not exactly obvious to the novice,
it not only gets the job done, but the findall()
method also has a number of other very
nice properties. It behaves properly in a boolean
context, and it never returns an incorrect index
(that is, -1.)

If you really did want to process all matches,
it's even easier.

John Roth

Neil Hodgson
Guest
Posts: n/a

 07-12-2004
Fernando Perez:

> In general I applaud python's efforts for being clear, readable,
> and not error-prone. But this is one of those cases where leaving
> the training wheels on causes genuine grief (I have in the past
> many times run into the example you mentioned, and have cursed
> it silently).

I hope this does not change as it makes analysis of the code easier.
Reading and understanding code is as important as writing it. Analysis of a
problem depends as much on restricting the set of possible causes ('it is
*not* the case that') as it does on generating a larger set of possible
causes ('it is the case that'). Pruning the possible cause tree is extremely
valuable and Python cooperates with a well thought out set of restrictions.
Being able to depend on the absence of assignments in if and while
statements is a benefit when fixing Python code over C/C++. Characterizing
these as "training wheels" and thus only of use to beginners is
unreasonable.

Neil

Fernando Perez
Guest
Posts: n/a

 07-12-2004
Neil Hodgson wrote:

> I hope this does not change as it makes analysis of the code easier.
> Reading and understanding code is as important as writing it. Analysis of a
> problem depends as much on restricting the set of possible causes ('it is
> *not* the case that') as it does on generating a larger set of possible
> causes ('it is the case that'). Pruning the possible cause tree is extremely
> valuable and Python cooperates with a well thought out set of restrictions.
> Being able to depend on the absence of assignments in if and while
> statements is a benefit when fixing Python code over C/C++. Characterizing
> these as "training wheels" and thus only of use to beginners is
> unreasonable.

Well, the problem here (and apparently others share this opinion) is that this
particular restriction genuinely forces kludgy code in certain circumstances.
As John Roth pointed out, the looping case is easily solved with iterators, but
Paul's original one is not.

I know that the if(x=0) bug in C/C++ is a potentially nasty one, having been
bitten by it myself in the past. It is also true that having this particular
option available allows certain kinds of code to be written in a clear and
concise manner. So yes, it is a slightly dangerous feature, but one which
offers true expressive power. Hence my characterization of it as 'training
wheels': I don't mean to say that only beginners can fall into the trap (even
Lance Armstrong can fall off a bike), but rather that experienced users will
know what to watch for, and will be willing to pay the price of potentially
falling for the liberty of going faster

Cheers,

f

Paul Rubin
Guest
Posts: n/a

 07-12-2004
"Neil Hodgson" <(E-Mail Removed)> writes:
> Pruning the possible cause tree is extremely valuable and Python
> cooperates with a well thought out set of restrictions.

If you're trying to add restrictions to prune a cause tree, how about
starting with private instance variables in classes and modules
instead of the silly underscore name mangling hack. Maybe you can

def f():
p = 3
def g():
p = 4
print 'g',p
g()
print 'f',p

f()

There's no way in g to set f's variable called 'p', which defeats the
purpose of nested functions as generally used since the days of Algol-60.

> Being able to depend on the absence of assignments in if and while
> statements is a benefit when fixing Python code over C/C++.

Not if it makes the code more complicated and bug-prone.

Donn Cave
Guest
Posts: n/a

 07-12-2004
Quoth Fernando Perez <(E-Mail Removed)>:
....
| Well, the problem here (and apparently others share this opinion) is that this
| particular restriction genuinely forces kludgy code in certain circumstances.
| As John Roth pointed out, the looping case is easily solved with iterators, but
| Paul's original one is not.
|
| I know that the if(x=0) bug in C/C++ is a potentially nasty one, having been
| bitten by it myself in the past. It is also true that having this particular
| option available allows certain kinds of code to be written in a clear and
| concise manner. So yes, it is a slightly dangerous feature, but one which
| offers true expressive power. Hence my characterization of it as 'training
| wheels': I don't mean to say that only beginners can fall into the trap (even
| Lance Armstrong can fall off a bike), but rather that experienced users will
| know what to watch for, and will be willing to pay the price of potentially
| falling for the liberty of going faster

I know people who would like this feature a lot, if it existed in
Python and if they wrote in Python. I know this from their C code,
which I have had miserable occasion to deal with. If what we get
is kludgy code, I accept that gladly in return for the guarantee
that I shall never have to deal with this kind of mess in Python.

Donn Cave, http://www.velocityreviews.com/forums/(E-Mail Removed)