检查某些字符的空字符串时,“ not in”身份运算符不起作用

时间:2019-05-19 07:14:17

标签: python python-3.x

当检查是否在空字符串变量中填充了某些字符时,该表达式始终被评估为true。如果新创建的字符串值为空,则应为false,它不包含任何字符,更不用说要检查的字符了。

当我硬编码不是检查表达式的字符的随机字符时,将被评估为false。

difficulty = ''

while difficulty not in 'EMH':
    print('Enter difficulty: E - Easy, M - Medium, H - Hard')
    difficulty = input().upper()

我希望看到调试器进入while循环。实际发生的情况是它继续经过while块而没有执行。

5 个答案:

答案 0 :(得分:6)

任何字符串中都存在一个空字符串。因此,当difficulty not in 'EMH'等于False时,您的条件difficulty将得出'';因此while循环的主体将不会执行。

In [24]: '' not in 'EMH'                                                                                                                                  
Out[24]: False

In [33]: '' in 'EMH'                                                                                                                                      
Out[33]: True

一个更好的方法可能是通过EMH将字符串list('EMH')转换为列表,这样EMEH之类的字符或空字符不会中断您的循环,或者避免从头开始

还有@Blckknght建议,一个更好的选择是使用None的默认值来解决问题。

In [3]: difficulty = None                                                                                                                                

In [4]: while difficulty not in list('EMH'): 
   ...:     print('Enter difficulty: E - Easy, M - Medium, H - Hard') 
   ...:     difficulty = input().upper() 
   ...:                                                                                                                                                   
Enter difficulty: E - Easy, M - Medium, H - Hard
A
Enter difficulty: E - Easy, M - Medium, H - Hard
B
Enter difficulty: E - Easy, M - Medium, H - Hard
C
Enter difficulty: E - Easy, M - Medium, H - Hard
EM
Enter difficulty: E - Easy, M - Medium, H - Hard
E

In [5]:      

答案 1 :(得分:6)

我认为您需要使用列表而不是字符串:

difficulty = ''

while difficulty not in ['E','M','H']:
    print('Enter difficulty: E - Easy, M - Medium, H - Hard')
    difficulty = input().upper()

答案 2 :(得分:2)

这是do-while循环条件的好例子。但是,python没有。请检查以下样式是否适合您:

while True:
    print('Enter difficulty: E - Easy, M - Medium, H - Hard')
    difficulty = input().upper()
    if difficulty not in 'EMH': #or in ['E', 'M', 'H']
        continue
    else:
        #do some logic
        break

我喜欢@Emmet B的建议,它在循环而不是字符串中使用['E','M','H']。这也很有意义,因为您希望将其中一个字符作为输入而不是字符集。

答案 3 :(得分:2)

如果您倾向于生活在Python的前沿,那么您可能有兴趣尝试使用当前正在开发的Python 3.8(但可以使用alpha版本)。赋值表达式是一个颇具争议的新功能(在PEP 572中引入),它使您可以使用:=在另一个表达式的中间进行赋值。

您正在执行的循环可以利用这种分配一次性完成输入和值检查,而无需在进入循环之前为difficulty分配虚假的初始值。

请注意,您可能仍想使用列表而不是在右边的字符串上使用not in,因为后者进行子字符串检查,而不是严格的序列成员资格测试。像difficulty not in 'EMH'这样的子字符串测试将为空字符串或多字母输入'EM''MH''EMH'带来意外的结果。如果您可能在某处使用不同的难度字符串作为字典键(例如,查找随难度设置而变化的统计信息),则可以直接测试输入是否是字典中的键,而不是构建单独的列表。

prompt = 'Enter difficulty: E - Easy, M - Medium, H - Hard\n'
while (difficulty := input(prompt).upper()) not in ['E', 'M', 'H']:
    pass  # or maybe: print("I'm sorry, I didn't understand that.")

# you can use `difficulty` down here

请注意,尽管您可以在此处 使用赋值表达式,但这并不是一个好主意,只是为了避免初始化变量。您最终将很多不同的东西捆绑在一起(whileinputupper调用,:=的赋值和{{1}测试),很容易对正在发生的事情感到困惑。确实,在上面的示例中,我最终创建了一个 different 变量(not in),因为否则该行太长了。

答案 4 :(得分:1)

已经提到了解决方案(恕我直言,使用list可以解决问题,并将变量初始化为None很干净,恕我直言),但是有很多不同的方法可以做到这一点(尽管Zen of Python的规则#13。

我还没有提到的一个建议是在while表达式中使用一个单独的布尔值,因此您不必使用任意无效值来初始化difficulty变量,并且不需要其他{ {1}} / continue / break / else语句:

pass