Skip to content Skip to sidebar Skip to footer

Python Xor Preference: Bitwise Operator Vs. Boolean Operators

Is there a preferred method for doing a logical XOR in python? For example, if I have two variables a and b, and I want to check that at least one exists but not both, I have two m

Solution 1:

One of the alternative way to achieve it is using any() and all() like:

if any([a, b]) and not all([a, b]):
    print "Either a or b is having value"

But based on the performance, below are the results:

  1. Using any() and all(): 0.542 usec per loop

    moin@moin-pc:~$ python -m "timeit""a='a';b='b';""any([a, b]) and not all([a, b])"1000000 loops, best of 3: 0.542 usec per loop
    
  2. Using bool(a) ^ bool(b): 0.594 usec per loop

    moin@moin-pc:~$ python -m "timeit""a='a';b='b';""bool(a) ^ bool(b)"1000000 loops, best of 3: 0.594 usec per loop
    
  3. Using (not a and b) or (a and not b): 0.0988 usec per loop

    moin@moin-pc:~$ python -m "timeit""a='a';b='b';""(not a and b) or (a and not b)"10000000 loops, best of 3: 0.0988 usec per loop
    

Clearly, your (not a and b) or (a and not b) is more efficient. Approximately 6 times efficient then others.


Comparison between few more flavors of and and or:

  1. Using a and not b or b and not a (as pointed by TemporalWolf): 0.116 usec per loop

    moin@moin-pc:~$ python -m "timeit""a='a';b='b';""a and not b or b and not a"10000000 loops, best of 3: 0.116 usec per loop
    
  2. Using (a or b) and not (a and b): 0.0951 usec per loop

    moin@moin-pc:~$ python -m "timeit""a='a';b='b';""(a or b) and not (a and b)"10000000 loops, best of 3: 0.0951 usec per loop
    

Note: This performance is evaluated for the value of a and b as str, and is dependent on the implementation of __nonzero__ / __bool__ / __or__functions as is mentioned by viraptor in comment.

Solution 2:

You can make it more readable than reducing the problem to XOR. Depending on the context these may be better:

ifsum((bool(a), bool(b))) == 1:  # this naturally extends to more valuesifbool(a) != bool(b):

So I think the best way is to go with what matches the actual meaning behind the XOR. Do you want them to not have the same value? Only one of them set? Something else?

If you use ^ and I'm reading the code, I'm going to assume you actually wanted to use bitwise operator and that it matters for some reason.

Is there an inherent performance benefit to using either one?

It's one statement. Unless you know it's a performance issue, it doesn't matter. If it is in a hot loop and your profiler shows you do need to optimise it, then you're likely better off using Cython or some other method of speeding it up.

Post a Comment for "Python Xor Preference: Bitwise Operator Vs. Boolean Operators"