>>> if 'arse':5
...
5
>>> if '':5
...
>>>
>>> if 'arse'==True:5
...
>>> 'arse' and 'arse'
'arse'
>>> 'arse' and 'flange'
'flange'
>>> 'arse'==True
False
>>> a = [1,2,3,4,5]
>>> b = [4,4,4,4,5]
>>> c = [x==y for x,y in zip(a,b)]
>>> c
[False, False, False, True, True]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[2, 3, 4, 4, 5]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[3, 4, 4, 4, 5]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[4, 4, 4, 4, 5]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[4, 4, 4, 4, 5]
I then spent a little time reading about logical operator and precedence in my Python Pocket Reference, because this was messing with my head. In x and y, if x is false, y is not evaluated. If x is true in some form, then y gets evaluated. If y happens to be a string, then the evaluation of y is returned, which is a string.
What we have then is a sort of trick if:else: statement. By writing…
condition and x or y
…we're achieving the same as…
if condition:
x
else:
y
This is remarkably handy stuff. Especially (as shown above) when used in a list comprehension. I'm not sure that it's particularly readable, but it's certainly more concise than the code I had previoulsy. More importantly, it works too (the previous code did not). The result is this (names changed to protect the innocent), which increments the values in a list, but only up to the corresponding limits specified in another list:
counters = [counter<boundary.upper and counter+1 or counter for counter,boundary in zip(counters,boundaries)]
The code I had in place prior looked something like this:
newList=[]
for counter,limit in zip(counters, limits):
if counter < limit.upperLimit:
newList.append[counter+1]
else:
newList.append[counter]
counters=newList