Python XOR 偏好:按位运算符与布尔运算符

Python XOR preference: bitwise operator vs. boolean operators

是否有在 python 中进行逻辑异或的首选方法?

例如,如果我有两个变量 a 和 b,并且我想检查是否至少存在一个而不是两个都存在,我有两种方法:

方法一(按位运算符):

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

方法二(布尔运算符):

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

使用其中任何一个都有固有的性能优势吗?方法 2 似乎更 "pythonic" 但方法 1 对我来说看起来更干净。这个related thread似乎表明它可能首先取决于ab是什么变量类型!

有任何有力的论据吗?

与将问题简化为 XOR 相比,您可以使其更具可读性。根据上下文,这些可能更好:

if sum((bool(a), bool(b))) == 1:  # this naturally extends to more values
if bool(a) != bool(b):

所以我认为最好的方法是与 XOR 背后的实际含义相匹配。你想让他们不具有相同的价值吗?只有其中一套?还有别的吗?

如果您使用 ^ 并且我正在阅读代码,我将假设您实际上想使用按位运算符并且出于某种原因它很重要。

Is there an inherent performance benefit to using either one?

这是一个声明。除非您知道这是性能问题,否则没关系。如果它处于热循环中并且您的探查器显示您确实需要对其进行优化,那么您最好使用 Cython 或其他一些加速方法。

另一种实现方法是使用 any()all(),例如:

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

但根据性能,结果如下:

  1. 使用any()all()每个循环0.542 usec

    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. 使用 bool(a) ^ bool(b)每个循环 0.594 微秒

    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. 使用 (not a and b) or (a and not b)每个循环 0.0988 微秒

    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
    

显然,您的 (not a and b) or (a and not b) 效率更高。效率约为其他产品的 6 倍。


andor几种口味的比较:

  1. 使用a and not b or b and not a(正如TemporalWolf所指出的):每个循环0.116 usec

    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. 使用(a or b) and not (a and b):每个循环 0.0951 usec

    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
    

注:此性能评估为ab的值为str,并依赖于实现__nonzero__ / __bool__ / __or__ functions 正如 viraptor 在评论中提到的那样。