Cleaning up conditionals

Jussi Piitulainen jussi.piitulainen at helsinki.fi
Sun Jan 1 02:44:30 EST 2017


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.)

> 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.

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.


More information about the Python-list mailing list