[Python-ideas] Break the dominance of boolean values in boolean context

Terry Reedy tjreedy at udel.edu
Tue Sep 13 00:27:15 CEST 2011


On 9/12/2011 4:20 PM, Lukas Lueg wrote:

> However the "or"-operator here grinds them
> both down to being just True or False.

Both 'and' and 'or' return one of their inputs unchanged and unground.

 >>> a = 'a'
 >>> b = 'b'
 >>> a or b
'a'
 >>> a and b
'b'
 >>> c = ''
 >>> a and c
''
 >>> c and a
''
 >>> a or c
'a'
 >>> c or a
'a'

If both inputs are True or False, then or course you always get one of 
them back. But again, no 'grind'ing.

 > Why is it, that we can override the behaviour of
 > arithmetic operations like "+, -, *, /", but not the boolean
 > operations like "and, or, xor, not" ?

In Python, 'and' and 'or' are *not* (functional) boolean operations. 
They are flow-control keywords that abbreviate in expression form an 
if-else statement pattern. They are compiled to similar bytecode.

def f1(a,b):
     return a and b

def f2(a,b):
     if not a: return a
     else: return b

from dis import dis
dis(f1)
dis(f2)
###
0 LOAD_FAST                0 (a)
3 JUMP_IF_FALSE_OR_POP     9
6 LOAD_FAST                1 (b)
9 RETURN_VALUE

0 LOAD_FAST                0 (a)
3 POP_JUMP_IF_TRUE        10
6 LOAD_FAST                0 (a)
9 RETURN_VALUE
10 LOAD_FAST                1 (b)
13 RETURN_VALUE

The difference is that the compiler does not notice that the 'a' to be 
returned is the same 'a' that it just tested and which is still sitting 
on the stack, so it reloads it or, if is were an expression, would 
recalculate it. There is no internal function that *could* be 
overloaded. In this sense, they are similar to 'lambda expressions, 
which abbreviate a simple def statement pattern and which compile to 
essentially the same bytecode as the def statement.

The xor bitwise int operator '^' can be overloaded: __xor__ and 
__rxor__. Logical xor can be implemented as bool(a)^bool(b).

Before there was a bool class, 'not not a' was the direct way to coerce 
a to a boolean value.

Anything that could be done with a hidden .__not__ method could also be 
done, and I would say, better done, with an overt .invert method. For 
instance, a mutable binary array class should likely have .invert to 
flip each member in-place.

As it is now, anyone reading 'not a' can depend on the result being a 
bool. And I think that is good.

-- 
Terry Jan Reedy




More information about the Python-ideas mailing list