Cleaning up conditionals

MRAB python at mrabarnett.plus.com
Fri Dec 30 21:47:45 EST 2016


On 2016-12-31 00:48, Deborah Swanson wrote:
>> On 30/12/16 23:00, Deborah Swanson wrote:
>> > Oops, indentation was messed up when I copied it into the email.
>> > Should be this:
>> >
>> > 		if len(l1[st]) == 0:
>> >                 if len(l2[st]) > 0:
>> >                     l1[st] = l2[st]
>> >             elif len(l2[st]) == 0:
>> >                 if len(l1[st]) > 0:
>> >                     l2[st] = l1[st]
>>
>> That's even worse!
>>
>> Anyway, ignoring all that, if what you are trying to do is
>> just do some
>> action based on a set of fixed comparisons that are known at
>> the top of
>> the function (and do not mutate depending on the path through the
>> function), then you can just cache the comparisons and then
>> compare the
>> resulting set of boolean results (note that my examples are
>> NOT based on
>> your use-case, it's just pseudo-code which happens to use
>> your expressions):
>>
>> state = (len(l1[st]) == 0, len(l2[st]) > 0)
>> if state == (True, False):
>>    pass
>> elif state == (False, True):
>>    pass
>>
>> ... etc.
>>
>> If the len() comparisons are tri-state (i.e., in some cases
>> you want to
>> know if the length is <, ==, or > 0, depending on one of the other
>> comparisons) then you can do something like:
>>
>> def clamp(foo):
>>    return min(max(-1, foo), 1)
>>
>> state = (clamp(cmp(len(l1[st]), 0), cmp(len(l2[st]), 0))
>> if state == (0, -1):
>>    pass
>> elif state == (1, -1):
>>    pass
>>
>> ... etc.
>>
>> I'm not sure this makes it much more readable though - but if
>> you make
>> the RHS of those comparisons a symbolic name you might be getting
>> somewhere -
>>
>> ACTION1 = (0, -1)
>> ACTION2 = (1, -1)
>> if state == ACTION1:
>>    pass
>> elif state == ACTION2:
>>    pass
>>
>> Hope that helps, E.
>>
>
> Thanks Erik, I really like your method of capturing the state and then
> reusing it. I'm sure I can use it in other situations. In this case,
> since I now have it down to:
>
> if not len(l1[st]) and len(l2[st]):
> 		l1[st] = l2[st]
> elif not len(l2[st]) and len(l1[st]):
> 		l2[st] = l1[st]
>
[snip]

An empty list is considered falsey and a non-empty list is considered truey:

 >>> bool([])
False
 >>> bool([0])
True

You don't care what the list's length is, only whether it's 0 or not, so:

if not l1[st] and l2[st]:
     l1[st] = l2[st]
elif not l2[st] and l1[st]:
     l2[st] = l1[st]



More information about the Python-list mailing list