Python XOR首选项:逐位运算符与布尔运算符
在python中执行逻辑XOR是否有首选方法 例如,如果我有两个变量a和b,并且我想检查是否至少存在一个变量,但不同时存在两个变量,那么我有两种方法: 方法1(按位运算符): 方法2(布尔运算符): 使用其中一种是否有内在的性能优势?方法2看起来更像“pythonic”,但方法1在我看来更干净。这似乎表明它可能取决于什么变量类型Python XOR首选项:逐位运算符与布尔运算符,python,xor,Python,Xor,在python中执行逻辑XOR是否有首选方法 例如,如果我有两个变量a和b,并且我想检查是否至少存在一个变量,但不同时存在两个变量,那么我有两种方法: 方法1(按位运算符): 方法2(布尔运算符): 使用其中一种是否有内在的性能优势?方法2看起来更像“pythonic”,但方法1在我看来更干净。这似乎表明它可能取决于什么变量类型a和b 任何一种方式都有强参数吗?您可以使其比将问题简化为XOR更具可读性。根据具体情况,这些可能更好: if sum((bool(a), bool(b))) == 1:
a
和b
任何一种方式都有强参数吗?您可以使其比将问题简化为XOR更具可读性。根据具体情况,这些可能更好:
if sum((bool(a), bool(b))) == 1: # this naturally extends to more values
if bool(a) != bool(b):
因此,我认为最好的方法是使用与XOR背后的实际含义相匹配的内容。是否希望它们不具有相同的值?只有一套?还有别的吗
如果您使用^
并且我正在阅读代码,那么我将假设您实际上想要使用位运算符,并且出于某种原因它很重要
使用其中一种是否有内在的性能优势
这是一种说法。除非你知道这是一个性能问题,否则这并不重要。如果它处于热循环中,并且您的探查器显示您确实需要对其进行优化,那么您最好使用Cython或其他加速方法。实现它的另一种方法是使用
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';" "a and not b or b and not a"
10000000 loops, best of 3: 0.116 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
bool(a)^bool(b)
:每个循环0.594 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
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)或(a和非b)
:每个循环0.0988 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
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)或(a和b)
效率更高。效率大约是其他产品的6倍
比较更多几种口味的
和以及或:
使用a而不是b或b而不是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
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)而不是(a和b)
:每个循环0.0951 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
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
的值进行评估,并取决于viraptor在评论中提到的\uuuuu非零函数的实现 另一个线程以什么方式不回答您的问题?正如链接线程“basic”中详述的那样,这两个是不等价的?你的意思是“布尔”,对吗?@TemporalWolf:Python没有“xor”布尔运算符,我需要在我正在编写的脚本中模拟这种行为。我特别询问两种不同xor实现的“pythonic”风格/性能。我知道它们是不等价的。@dizzyf我会说defXOR(a,b):返回(a而不是b)或(b而不是a)
是最具python风格的方法,然后调用xor(a,b)
,尽管这假设a
和b
是布尔值。如果需要,请包装它们。正如用户自己提到的方法,我不认为将其标记为重复是个好主意。他更感兴趣的是哪个应该是首选的以及为什么。从技术上讲,如果(不是a)不是(不是b):
会稍微快一点,相当于如果(a)!=bool(b):
,至少在CPython上是这样,因为not
是语法(添加一元\u not
指令),而bool
添加加载\u全局
和调用函数
(两者都比较昂贵)。切换到不是
意味着你遵循的代码路径只处理身份平等,没有丰富的比较机制。当然,但再次强调:“除非你知道这是一个性能问题,否则没关系。”我马上就知道什么是bool(a)=布尔(b)
。我必须花时间弄清楚什么是(不是a)不是(不是b)
做的。a而不是b或b而不是a是等价的和
的值大于或
。这取决于\uuuuuu非零\uuuuuuu
/\uuuuuuu或的实现。对于一个str来说,这是微不足道的。对于远程调用的东西,它不是。Op没有提到使用的值。@anonymous我想你可能也看到了和/或短路的好处:把它作为一个列表运行只需要一半的时间:对于str in(((bool(a)^bool(b)),“任意([a,b]),而不是全部([a,b]),“a而不是b或b而不是a”):打印timeit.timeit([%s表示范围内的a(2)对于范围(2)]%str中的b
@viraptor:同意你的观点。这完全取决于这些功能的实现。将您的评论添加到answer@TemporalWolf:为您在回答中提到的表达式添加了timeit
stats