是否有一种在python中进行逻辑XOR的首选方法?
例如,如果我有两个变量a和b,并且我想检查至少有一个变量而不是两个变量,我有两种方法:
方法1(按位运算符):
if bool(a) ^ bool(b):
do x
方法2(布尔运算符):
if (not a and b) or (a and not b):
do x
使用其中任何一个都有固有的性能优势吗?方法2似乎更多" pythonic" 但方法1对我来说看起来更干净。这个related thread似乎表明它可能取决于a
和b
变量类型的位置!
任何强有力的论据?
答案 0 :(得分:1)
实现它的另一种方法是使用any()
和all()
,如:
if any([a, b]) and not all([a, b]):
print "Either a or b is having value"
但根据表现,以下是结果:
使用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
使用bool(a) ^ bool(b)
:每个循环0.594 usec
moin@moin-pc:~$ python -m "timeit" "a='a';b='b';" "bool(a) ^ bool(b)"
1000000 loops, best of 3: 0.594 usec per loop
每个循环使用(not a and b) or (a and not b)
: 0.0988 usec
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倍。
and
和or
的几种风格之间的比较:
使用a and not b or b and not a
(由 TemporalWolf指定):每个循环使用0.116个
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
每个循环使用(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
注意:此效果的评估值为a
和b
str
,并取决于__nonzero__
的实施情况/ __bool__
/ __or__
函数,如评论中 viraptor 所述。
答案 1 :(得分:0)
除了将问题减少到XOR之外,您可以使其更具可读性。根据具体情况,这可能会更好:
if sum((bool(a), bool(b))) == 1: # this naturally extends to more values
if bool(a) != bool(b):
所以我认为最好的方法是选择与XOR背后的实际含义相匹配的东西。你想让他们没有相同的价值吗?只有其中一个设置?还有别的吗?
如果您使用^
并且我正在阅读代码,我将假设您实际上想要使用按位运算符,并且由于某种原因这很重要。
使用其中任何一个都有固有的性能优势吗?
这是一个声明。除非你知道它是性能问题,否则无所谓。如果它处于热循环中并且您的探查器显示您确实需要对其进行优化,那么您最好使用Cython或其他一些加速它的方法。