今天我遇到了这样一个问题:
source='reset'
print(source.find('%reset') != -1 | source.strip().startswith('reset'))
得到的结果:False
我希望用以上代码判断source
变量中是否含有字符串'reset'
或者'%reset'
。但是出乎意料的是,明明以上两个表达式中的第二个是True
,第一个是False
,为什么最终算出来是False
呢?
在一些教程中,直接写明了python中,|
和or
在逻辑运算时意思相同。但这样的表述并不严谨,因为会忽略运算优先级的问题。
我曾经学过在C语言。在C语言中,||
表示的是逻辑或,而|
表示的则是按位或。在我看来,这种运算符标记,是比较方便的。
在python语言中没有||
,只有|
符号。当|
两端可位运算时,就执行位运算。特别地,两端的变量为布尔型(True
、False
)的时候,就是逻辑或的关系。
从C语言过渡到主攻python之后,我便顺理成章的习惯于使用|
作为判断标志,类似于C语言的||
那样。一年多来一直没有遇到问题,或者是遇到问题后加括号就解决了。
今天,我终于打算上网深究一下这个问题。原来,我一直将|
当成C语言中的||
。殊不知,运算的优先级是有不同的。在C语言中,==
是优先于||
,但是Python中则是|
运算符优先于==
。
而实际上,python语言的|
,和C语言中的|
含义是一样的,都是按位运算的意思。在C语言中|
在某些场合下也可以替换||
,但也会引入优先级问题。
回到上面的问题:
source.find('%reset') != -1 | source.strip().startswith('reset')
代码中,由于!=
优先级低于|
,所以首先计算|
两侧的值。-1|source.strip().startswith('reset')
,两端的值分别为-1|0
。进行按位或计算,得到-1。
接下来再计算source.find('%reset')!=-1
,由于source
中明显不含字符串'%reset'
,所以左端值为-1。由此整个式子化简为-1!=-1
,最终结果为False。
这样,我们就找到了这个问题的症结所在。那么如何解决这个问题呢?
首先的方法就是加括号。
>>>print((source.find('%reset') != -1) | (source.strip().startswith('reset')))
True
其次,使用and 、 or
来代替| 、 &
。and、or
的优先级在==
(同优先级还有!=、<=、<
等)之后,由此,即使不加括号也能算出希望的结果。
>>>print(source.find('%reset') != -1 or source.strip().startswith('reset'))
True
最后说一句,使用or
代替|
还有诸多好处。假设两边的判断语句是100*100==10000
和999*999==10000
,那么如果用or
的话,计算出第一个语句结果为True
,就可以直接向下执行了;作为对比,用|
(当然,要向上文那样加括号)的话,就必须算出两边的结果,按位或之后再向下执行。
于是得出结论:|
是按位或,或逻辑运算有运算优先级上的不同。在逻辑判断的场合下,如果使用or
,有助于简化括号层数,并且有助于加速。因此一般情况下推荐使用or。