Python条件判断的优先级

背景

做LeetCode的时候经常能够发现很多基本功不扎实的问题。
这一次是在做一道简单题时候忽视的条件判断优先级的问题

题目连接:https://leetcode.cn/problems/count-the-number-of-vowel-strings-in-range

代码部分


问题代码

1
2
3
4
5
6
7
8
9
10
class Solution:
def vowelStrings(self, words: List[str], left: int, right: int) -> int:
words = words[left : right + 1]
n = len(words)
print(n)
res = 0
for i in range(n):
if words[i][0] == 'a' or words[i][0] == 'e' or words[i][0] == 'i' or words[i][0] == 'o' or words[i][0] == 'u' and words[i][-1] == 'a' or words[i][-1] == 'e' or words[i][-1] == 'i' or words[i][-1] == 'o' or words[i][-1] == 'u':
res += 1
return res

正确代码

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def vowelStrings(self, words: List[str], left: int, right: int) -> int:
words = words[left : right + 1]
n = len(words)
print(n)
res = 0
for i in range(n):
if words[i][0] == 'a' or words[i][0] == 'e' or words[i][0] == 'i' or words[i][0] == 'o' or words[i][0] == 'u':
if words[i][-1] == 'a' or words[i][-1] == 'e' or words[i][-1] == 'i' or words[i][-1] == 'o' or words[i][-1] == 'u':
res += 1
return res

二者的差别就在如何衔接 orand 之间的关系上。

具体分析

分析错误代码的bug:

在第二段错误代码中,条件判断部分存在问题。以下是有问题的代码片段:

1
2
if words[i][0] == 'a' or words[i][0] == 'e' or words[i][0] == 'i' or words[i][0] == 'o' or words[i][0] == 'u' and words[i][-1] == 'a' or words[i][-1] == 'e' or words[i][-1] == 'i' or words[i][-1] == 'o' or words[i][-1] == 'u':
res += 1

问题出在逻辑运算符的优先级上。在Python中,and 运算符的优先级高于 or 运算符,因此该条件判断实际上被解释为:

1
2
if words[i][0] == 'a' or words[i][0] == 'e' or words[i][0] == 'i' or words[i][0] == 'o' or (words[i][0] == 'u' and words[i][-1] == 'a') or words[i][-1] == 'e' or words[i][-1] == 'i' or words[i][-1] == 'o' or words[i][-1] == 'u':
res += 1

由于 or 运算符的短路特性,只要 words[i][0] 的首字母为元音字母之一,整个条件判断就会被认为是True,导致res增加。而第二个部分 words[i][-1] == 'a'words[i][-1] == 'e'等都是单独的条件,不会影响整个条件判断的结果。

修正该bug的方法是使用括号明确指定条件的分组,确保逻辑关系正确。以下是修正后的代码:

1
2
if (words[i][0] == 'a' or words[i][0] == 'e' or words[i][0] == 'i' or words[i][0] == 'o' or words[i][0] == 'u') and (words[i][-1] == 'a' or words[i][-1] == 'e' or words[i][-1] == 'i' or words[i][-1] == 'o' or words[i][-1] == 'u'):
res += 1

这样修改后,条件判断会首先检查首字母是否为元音字母,然后再检查末尾字母是否为元音字母,两个条件都满足时才会增加res的值。