Python XOR preference: bitwise operator vs. boolean operators [duplicate]

与世无争的帅哥 提交于 2019-12-11 05:34:16

问题


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 methods:

Method 1 (bitwise operator):

if bool(a) ^ bool(b):
    do x

Method 2 (boolean operators):

if (not a and b) or (a and not b):
    do x

Is there an inherent performance benefit to using either one? Method 2 seems more "pythonic" but Method 1 looks much cleaner to me. This related thread seems to indicate that it might depend on what variable types a and b are in the first place!

Any strong arguments either way?


回答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.




回答2:


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

if sum((bool(a), bool(b))) == 1:  # this naturally extends to more values
if bool(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.



来源:https://stackoverflow.com/questions/40096616/python-xor-preference-bitwise-operator-vs-boolean-operators

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!