Wednesday, September 13, 2006

Logical exclusive-or in Python

Python has and, or, and not logical operators, and it has & (and), | (or), ~ (not), and ^ (xor) bitwise operators, but no logical xor. However, since you can pass any object to bool() and get back a boolean (True, False), and booleans are automatically convertable to integers (1, 0), the bitwise operators work on booleans as well:
>>> True ^ True
False
>>> True ^ False
True
>>> False ^ False
False
>>>

However, if testing things that are not actually booleans or integers, you need to wrap them in bool() first:

>>> "foo" ^ None
Traceback (most recent call last):
File "", line 1, in ?
TypeError: unsupported operand type(s) for ^: 'str' and 'NoneType'
>>> bool("foo") ^ bool(None)
True

Updated 2006-09-14. I realized you could also use is not with booleans to get an xor operator:

>>> True is not True
False
>>> True is not False
True
>>> False is not False
False

This seems more Pythonic. As with ^, non-booleans must be wrapped with bool():

>>> bool("foo") is not bool(None)
True
>>> bool("foo") is not bool("bar")
False

2 comments:

Bryan said...

Thanks for the tip! Note on using 'is not' instead of ^, if you want to compare more than two items you need to use parens. You don't have to using ^

>>> True ^ False ^ False
True

>>> True is not False is not False
False

oops. Do this:

>>> (True is not False) is not False
True

That's better.

cool-RR said...

Great post!