How do you get the logical xor of two variables in Python?
For example, I have two variables that I expect to be strings. I want to test that only one of them contains a True value (is not None or the empty string):
str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
print "ok"
else:
print "bad"
The ^
operator seems to be bitwise, and not defined on all objects:
>>> 1 ^ 1
0
>>> 2 ^ 1
3
>>> "abc" ^ ""
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ^: 'str' and 'str'
a xor a
is defined as (a and not b) or (not a and b)
, and so a xor b
, when a
and b
are character strings, or any other types, should yield whatever (a and not b) or (not a and b)
yields.
If you're already normalizing the inputs to booleans, then != is xor.
bool(a) != bool(b)
You can always use the definition of xor to compute it from other logical operations:
(a and not b) or (not a and b)
But this is a little too verbose for me, and isn't particularly clear at first glance. Another way to do it is:
bool(a) ^ bool(b)
The xor operator on two booleans is logical xor (unlike on ints, where it's bitwise). Which makes sense, since bool
is just a subclass of int
, but is implemented to only have the values 0
and 1
. And logical xor is equivalent to bitwise xor when the domain is restricted to 0
and 1
.
So the logical_xor
function would be implemented like:
def logical_xor(str1, str2):
return bool(str1) ^ bool(str2)
Credit to Nick Coghlan on the Python-3000 mailing list.
(not b and a) or (not a and b)
so that it returns the string if there was one, which seems like the pythonic way for the function to operate.
Bitwise exclusive-or is already built-in to Python, in the operator
module (which is identical to the ^
operator):
from operator import xor
xor(bool(a), bool(b)) # Note: converting to bools is essential
xor(1, 2)
returns 3
. From the docstring: xor(a, b) -- Same as a ^ b.
Remember that anything imported from operator
is just a functional form of an existing builtin infix operator.
bool
type overloads __xor__
to return booleans. It'll work just fine, but its overkill when bool(a) ^ bool(b)
does exactly the same thing.
^
operator calls __xor__
internally.
bool
type implements the __xor__
method specifically because ^
calls it. The point being that bool(a) ^ bool(b)
works fine, there is no need to use the operator.xor()
function here.
As Zach explained, you can use:
xor = bool(a) ^ bool(b)
Personally, I favor a slightly different dialect:
xor = bool(a) + bool(b) == 1
This dialect is inspired from a logical diagramming language I learned in school where "OR" was denoted by a box containing ≥1
(greater than or equal to 1) and "XOR" was denoted by a box containing =1
.
This has the advantage of correctly implementing exclusive or on multiple operands.
"1 = a ^ b ^ c..." means the number of true operands is odd. This operator is "parity".
"1 = a + b + c..." means exactly one operand is true. This is "exclusive or", meaning "one to the exclusion of the others".
(((((True + True)==1)+False)==1)+True)==1
. The answer given here totally generalizes to multiple operands.
True + True + False + True
, you do get 3
, and True + True + False + True == 3
gives back True
while True + True + False + True == 1
gives back False
. In other words, the answer here doesn't generalize correctly; for it to do so, you need to do additional work. Meanwhile a simple True ^ True ^ False ^ True
works as expected.
True
, a multi-arity XOR. This is a different operation than, for example, A XOR B XOR ... XOR Z
. In other words, if you plan to use the addition-based version, then upon submitted the operands in True + True + False + True
you should expect the result to be False
since more than one of those is True
, which works if the condition checks for == 1
.
Python logical or: A or B: returns A if bool(A) is True, otherwise returns B
Python logical and: A and B: returns A if bool(A) is False, otherwise returns B
To keep most of that way of thinking, my logical xor definintion would be:
def logical_xor(a, b):
if bool(a) == bool(b):
return False
else:
return a or b
That way it can return a
, b
, or False
:
>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'
and
and or
won't return logical value. 'foo' and 'bar'
returns 'bar'
...
xor
implementation that is consistent with the built-in and
and or
. However, of course, in practical situations, bool(a) ^ bool(b)
or even a ^ b
(if a
and b
are known to be bool
) are more concise of course.
I've tested several approaches and not a != (not b)
appeared to be the fastest.
Here are some tests
%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop
%timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop
%timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop
Edit: Examples 1 and 3 above are missing parenthes so result is incorrect. New results + truth()
function as ShadowRanger suggested.
%timeit (not a) ^ (not b) # 47 ns
%timeit (not a) != (not b) # 44.7 ns
%timeit truth(a) != truth(b) # 116 ns
%timeit bool(a) != bool(b) # 190 ns
from operator import truth
at the top of the module, and test truth(a) != truth(b)
. bool
being a constructor has a lot of unavoidable overhead at the C level (it must accept arguments as the equivalent of *args, **kwargs
and parse the tuple
and dict
to extract them), where truth
(being a function) can use an optimized path that doesn't require either a tuple
or a dict
, and runs in about half the time of bool
based solutions (but still longer than not
based solutions).
Python has a bitwise exclusive-OR operator, it's ^
:
>>> True ^ False
True
>>> True ^ True
False
>>> False ^ True
True
>>> False ^ False
False
You can use it by converting the inputs to booleans before applying xor (^
):
bool(a) ^ bool(b)
(Edited - thanks Arel)
^
is a bitwise xor (not logical xor like the question asked). bool(2) ^ bool(3)
gives a different answer than bool(2 ^ 3)
.
a ^ b
is polymorph. If a
and b
are bool
instances, the result will be bool
as well. This behavior can hardly be called a "bitwise" xor.
^
as bitwise, even though it's an interesting point that types are preserved for bool
and int
types. Note: True ^ 2
is 3
, demonstrating how it is indeed bitwise.
bool ^ int
case is kind of casting everything to int
first. Still, Python has built-in the ^
operator for many bits in int
and for the one bit represented in a bool
, so both are bitwise, but the bitwise xor for a single bit just is the logical xor for booleans.
xor
, coming from an engineering background, to me this instinctively feels like a mathematical power, ie 2^3 = pow(2,3)
which means I always explicitly comment to prevent confusion.
Simple, easy to understand:
sum(bool(a), bool(b)) == 1
If an exclusive choice is what you're after, i.e. to select 1
choice out of n
, it can be expanded to multiple arguments:
sum(bool(x) for x in y) == 1
sum(map(bool, y)) % 2 == 1
sum
if you just have 2 variables, bool(a) + bool(b) == 1
does the same thing.
To get the logical xor of two or more variables in Python:
Convert inputs to booleans Use the bitwise xor operator (^ or operator.xor)
For example,
bool(a) ^ bool(b)
When you convert the inputs to booleans, bitwise xor becomes logical xor.
Note that the accepted answer is wrong: !=
is not the same as xor in Python because of the subtlety of operator chaining.
For instance, the xor of the three values below is wrong when using !=
:
True ^ False ^ False # True, as expected of XOR
True != False != False # False! Equivalent to `(True != False) and (False != False)`
(P.S. I tried editing the accepted answer to include this warning, but my change was rejected.)
As I don't see the simple variant of xor using variable arguments and only operation on Truth values True or False, I'll just throw it here for anyone to use. It's as noted by others, pretty (not to say very) straightforward.
def xor(*vars):
result = False
for v in vars:
result = result ^ bool(v)
return result
And usage is straightforward as well:
if xor(False, False, True, False):
print "Hello World!"
As this is the generalized n-ary logical XOR, it's truth value will be True whenever the number of True operands is odd (and not only when exactly one is True, this is just one case in which n-ary XOR is True).
Thus if you are in search of a n-ary predicate that is only True when exactly one of it's operands is, you might want to use:
def isOne(*vars):
result = False
for v in vars:
if result and v:
return False
else:
result = result or v
return result
(bool(False) is False) == True
. You can just use False
on those lines.
Rewarding thread:
Anoder idea... Just you try the (may be) pythonic expression «is not» in order to get behavior of logical «xor»
The truth table would be:
>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>
And for your example string:
>>> "abc" is not ""
True
>>> 'abc' is not 'abc'
False
>>> 'abc' is not ''
True
>>> '' is not 'abc'
True
>>> '' is not ''
False
>>>
However; as they indicated above, it depends of the actual behavior you want to pull out about any couple strings, because strings aren't boleans... and even more: if you «Dive Into Python» you will find «The Peculiar Nature of "and" and "or"» http://www.diveintopython.net/power_of_introspection/and_or.html
Sorry my writed English, it's not my born language.
Regards.
I know this is late, but I had a thought and it might be worth, just for documentation. Perhaps this would work:np.abs(x-y)
The idea is that
if x=True=1 and y=False=0 then the result would be |1-0|=1=True if x=False=0 and y=False=0 then the result would be |0-0|=0=False if x=True=1 and y=True=1 then the result would be |1-1|=0=False if x=False=0 and y=True=1 then the result would be |0-1|=1=True
abs
, python interprets negative numbers as truthy, although this is very obscure imo (what does if (x > 1) - (y > 3)
mean?
Given that A and B are bools.
A is not B
Exclusive Or is defined as follows
def xor( a, b ):
return (a or b) and not (a and b)
and
and or
do short-circuit. Any xor
implementation can't short-circuit, so there is already a discrepancy; therefore, there is no reason that xor
should operate like and
+or
do.
Some of the implementations suggested here will cause repeated evaluation of the operands in some cases, which may lead to unintended side effects and therefore must be avoided.
That said, a xor
implementation that returns either True
or False
is fairly simple; one that returns one of the operands, if possible, is much trickier, because no consensus exists as to which operand should be the chosen one, especially when there are more than two operands. For instance, should xor(None, -1, [], True)
return None
, []
or False
? I bet each answer appears to some people as the most intuitive one.
For either the True- or the False-result, there are as many as five possible choices: return first operand (if it matches end result in value, else boolean), return first match (if at least one exists, else boolean), return last operand (if ... else ...), return last match (if ... else ...), or always return boolean. Altogether, that's 5 ** 2 = 25 flavors of xor
.
def xor(*operands, falsechoice = -2, truechoice = -2):
"""A single-evaluation, multi-operand, full-choice xor implementation
falsechoice, truechoice: 0 = always bool, +/-1 = first/last operand, +/-2 = first/last match"""
if not operands:
raise TypeError('at least one operand expected')
choices = [falsechoice, truechoice]
matches = {}
result = False
first = True
value = choice = None
# avoid using index or slice since operands may be an infinite iterator
for operand in operands:
# evaluate each operand once only so as to avoid unintended side effects
value = bool(operand)
# the actual xor operation
result ^= value
# choice for the current operand, which may or may not match end result
choice = choices[value]
# if choice is last match;
# or last operand and the current operand, in case it is last, matches result;
# or first operand and the current operand is indeed first;
# or first match and there hasn't been a match so far
if choice < -1 or (choice == -1 and value == result) or (choice == 1 and first) or (choice > 1 and value not in matches):
# store the current operand
matches[value] = operand
# next operand will no longer be first
first = False
# if choice for result is last operand, but they mismatch
if (choices[result] == -1) and (result != value):
return result
else:
# return the stored matching operand, if existing, else result as bool
return matches.get(result, result)
testcases = [
(-1, None, True, {None: None}, [], 'a'),
(None, -1, {None: None}, 'a', []),
(None, -1, True, {None: None}, 'a', []),
(-1, None, {None: None}, [], 'a')]
choices = {-2: 'last match', -1: 'last operand', 0: 'always bool', 1: 'first operand', 2: 'first match'}
for c in testcases:
print(c)
for f in sorted(choices.keys()):
for t in sorted(choices.keys()):
x = xor(*c, falsechoice = f, truechoice = t)
print('f: %d (%s)\tt: %d (%s)\tx: %s' % (f, choices[f], t, choices[t], x))
print()
Sometimes I find myself working with 1 and 0 instead of boolean True and False values. In this case xor can be defined as
z = (x + y) % 2
which has the following truth table:
x
|0|1|
-+-+-+
0|0|1|
y -+-+-+
1|1|0|
-+-+-+
Many folks, including myself, need an xor
function that behaves like an n-input xor circuit, where n is variable. (See https://en.wikipedia.org/wiki/XOR_gate). The following simple function implements this.
def xor(*args):
"""
This function accepts an arbitrary number of input arguments, returning True
if and only if bool() evaluates to True for an odd number of the input arguments.
"""
return bool(sum(map(bool,args)) % 2)
Sample I/O follows:
In [1]: xor(False, True)
Out[1]: True
In [2]: xor(True, True)
Out[2]: False
In [3]: xor(True, True, True)
Out[3]: True
You use the same XOR operator like in C, which is ^
.
I don't know why, but the most upvoted solution suggests bool(A) != bool(B)
, while I would say - in conformity with C's ^
's operator, the most obvious solution is:
bool(A) ^ bool(B)
which is more readable and immediately understandable for anyone coming from C
or any C
-derived language ...
when doing code-golfing, probably
not A ^ (not B)
will be the winner. with not
as converter for boolean (one letter less than bool()
. And for the first expression in some cases one can leave out the parantheses. Well, it depends, in cases where one has to do not(A) ^ (not(B))
, the bool()
needs same amount of letters ...
not not A
is another way to get the same result as bool(A)
without a function call.
How about this?
(not b and a) or (not a and b)
will give a
if b
is false
will give b
if a
is false
will give False
otherwise
Or with the Python 2.5+ ternary expression:
(False if a else b) if b else a
Xor is ^
in Python. It returns :
A bitwise xor for ints
Logical xor for bools
An exclusive union for sets
User-defined results for classes that implements __xor__.
TypeError for undefined types, such as strings or dictionaries.
If you intend to use them on strings anyway, casting them in bool
makes your operation unambiguous (you could also mean set(str1) ^ set(str2)
).
This is how I would code up any truth table. For xor in particular we have:
| a | b | xor | |
|---|----|-------|-------------|
| T | T | F | |
| T | F | T | a and not b |
| F | T | T | not a and b |
| F | F | F | |
Just look at the T values in the answer column and string together all true cases with logical or. So, this truth table may be produced in case 2 or 3. Hence,
xor = lambda a, b: (a and not b) or (not a and b)
It's easy when you know what XOR does:
def logical_xor(a, b):
return (a and not b) or (not a and b)
test_data = [
[False, False],
[False, True],
[True, False],
[True, True],
]
for a, b in test_data:
print '%r xor %s = %r' % (a, b, logical_xor(a, b))
This gets the logical exclusive XOR for two (or more) variables
str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
any([str1, str2]) and not all([str1, str2])
The first problem with this setup is that it most likely traverses the whole list twice and, at a minimum, will check at least one of the elements twice. So it may increase code comprehension, but it doesn't lend to speed (which may differ negligibly depending on your use case).
The second problem with this setup is that it checks for exclusivity regardless of the number of variables. This is may at first be regarded as a feature, but the first problem becomes a lot more significant as the number of variables increases (if they ever do).
XOR is implemented in operator.xor
.
Just because I haven't seen it mentioned elsewhere, this also does the trick:
def logical_xor(a, b):
return not b if a else bool(b)
I'm not sure if it's "better"/more readable/more pythonic than the accepted solution bool(a) != bool(b).
The way that Python handles logic operations can be confusing, so my implementation gives the user the option (by default) of a simple True/False answer. The actual Python result can be obtained by setting the optional third arg to None.
def xor(a, b, true=True, false=False): # set true to None to get actual Python result
ab1 = a and not b
ab2 = not a and b
if bool(ab1) != bool(ab2):
return (ab1 or ab2) if true is None else true
else:
return false
Here's a generalization.
def xor(*orands):
return sum(bool(x) for x in orands) == 1
You can test it with
# test
from itertools import product
for a, b, c in product((False, True), repeat=3):
print(f'{int(a)}{int(b)}{int(c)}|{xor(a,b,c)}')
Output:
000|False 001|True 010|True 011|False 100|True 101|False 110|False 111|False
We can easily find xor of two variables by the using:
def xor(a,b):
return a !=b
Example:
xor(True,False) >>> True
xor("hey", "there")
>>> True, but that's not what we want
Success story sharing
bool(a) is not bool(b)
instead?