Cleaning up conditionals

Deborah Swanson python at deborahswanson.net
Sun Jan 1 18:50:25 EST 2017



> -----Original Message-----
> From: Python-list 
> [mailto:python-list-bounces+python=deborahswanson.net at python.o
> rg] On Behalf Of Jussi Piitulainen
> Sent: Saturday, December 31, 2016 11:45 PM
> To: python-list at python.org
> Subject: Re: Cleaning up conditionals
> Importance: High
> 
> 
> Deborah Swanson writes:
> 
> > Jussi Piitulainen wrote:
> >> Sent: Saturday, December 31, 2016 8:30 AM
> >> Deborah Swanson writes:
> >> 
> >> > Is it possible to use some version of the "a = expression1 if 
> >> > condition else expression2" syntax with an elif? And for 
> >> > expression1 and expression2 to be single statements?  That's the 
> >> > kind of shortcutting I'd like to do, and it seems like 
> python might 
> >> > be able to do something like this.
> >> 
> >> I missed this question when I read the thread earlier. The
> >> answer is simply to make expression2 be another conditional 
> >> expression. I tend to write the whole chain in parentheses. 
> >> This allows multi-line layouts like the following alternatives:
> >> 
> >> a = ( first if len(first) > 0
> >>       else second if len(second) > 0
> >>       else make_stuff_up() )
> >> 
> >> a = ( first if len(first) > 0 else
> >>       second if len(second) > 0 else
> >>       make_stuff_up() )
> >> 
> >> Expression1 and expression2 cannot be statements. Python
> >> makes a formal distinction between statements that have an 
> >> effect and expressions that have a value. All components of a 
> >> conditional expression must be expressions. A function call 
> >> can behave either way but I think it good style that the 
> >> calls in expresions return values.
> >
> > While I'm sure these terniaries will be useful for future 
> problems, I 
> > couldn't make the second one work for my current problem.
> 
> (Note that those two things are just different layouts for 
> the exact same conditional expression.)
> 
> > I got as far as:
> >
> > a = l1[v] if len(l1[v] > 0 else 
> >     l2[v] if len(l2[v] > 0 else
> 
> (Parentheses needed, otherwise the first line is expected to 
> be a whole statement and then the unfinished expression in it 
> is considered
> malformed.)

Thanks, I missed that. (Never ran the code because I couldn't finish
it.)
 
> > And didn't finish it because I couldn't see what a should 
> be. I want 
> > it to be l2[v] if the first clause is true, and l1[v] if 
> the second. 
> > If I was computing a value, this would work beautifully, 
> but I don't 
> > see how it can if I'm choosing a list element to assign to. Maybe I 
> > just can't see it.
> 
> Do you here mean condition when you say clause? Then, if the 
> first condition is true, any other condition is not 
> considered at all. When you come to the final else-branch, 
> you know that all conditions in the chain were false.

This is fine, in general we wouldn't know if either l1[v] or l2[v] are
non-empty, and it would be possible that both are empty. But this
function is only called if they're not equal, which means one of them
could be empty, or that the two fields are both non-empty and different
from each other (my second test).

So I had two problems implementing this code. The first one was that the
final else was a dead end and I didn't see what to replace it with
(though I can see now what it should be). But the biggest problem is
what a is.  It should be either the location l1[v] or the location
l2[v], but by making it a scalar, a is not in either row. It's just a
disconnected variable, so the statement doesn't assign anything to a
field in either row.

> I thought you originally wanted to keep l1[v] if it was 
> non-empty, which is what the code here says, but this time 
> your prose seems different. Anyhow, since you want a value 
> when all conditions in the chain of conditions are false, you 
> want a value to use when the field is empty in both records. 
> To change nothing, store the old empty value back; or you can 
> supply your own default here.
> 
> With your particular conditions of non-emptiness, which is 
> taken to be truth, you can achieve variations of this result 
> with any of the following statements:
> 
> w = ( l1[v] if len(l1[v]) > 0 else
>       l2[v] if len(l2[v]) > 0 else
>       l1[v] )
> 
> x = l1[v] if l1[v] else l2[v] if l2[v] else l1[v]
> 
> y = l1[v] or l2[v] or l1[v]
> 
> z = l1[v] or l2[v]
> 
> The last one, which I originally suggested (and still prefer 
> when otherwise appropriate), is subtly different from the 
> others. That difference should be irrelevant.

I agree, if the goal was to capture one of the field values in a scalar
value.

Maybe it would help if I give a couple rows of (made up) data to show
what I mean (first row is field titles):

......Description		Date		State/co	Kind
Notes
l1	2 br, Elk Plains	12-26		WA/pi		house
garage, w/d
l2	2 br, Elk Plains	12-29

In this case, I want to copy the values from l1 to l2.

Or I could have, say, if I didn't see the one on 12-26 until after
12-29: 
l1	2 br, Elk Plains	12-26		
l2	2 br, Elk Plains	12-29		WA/pi		house
garage, w/d

In this case, I want to copy the values from l2 to l1.

While I still don't see how any of your versions would solve this
problem, it remains true that your form would be excellent for assigning
to a scalar variable, which is what they claim to do.





More information about the Python-list mailing list