如何使用any()函数检查变量是否匹配列表中的任何项目?
补充说明:我想做的是这样的:我让用户输入一个月份,然后代码会检查这个月份是否正确,方法是查看每一个在月份列表中的项目。如果没有找到这个月份,我希望用户能重新输入。
以下是代码:
months_list=["January", "February", "March", "April", "May", "June", "July"]
answer=raw_input("Month? \n")
while any(item.lower() != answer.lower() for item in months_list):
print("Sorry, didn't recognize your answer, try again")
answer=raw_input("Type in Month\n")
但是无论这个月份是否在列表中,我的代码一直在循环。我希望这样能更清楚地说明问题。谢谢大家的帮助!
3 个回答
13
要检查一个元素是否在某个集合里,可以使用 in
这个关键词:
>>> a = ['a','b','c','d']
>>> 'a' in a
True
>>> 'z' in a
False
24
any(a)
的意思是“a
里面有没有任何一个项目是‘真’的”?结果是True
,因为a
里的每个项目都是‘真’的。(任何非零长度的字符串都是‘真’的,而a
里的每个项目都是非零长度的字符串。)
然后你把这个结果True
和,比如说"A"
进行比较。True
和"A"
是不相等的,所以这个比较的结果当然是False
。
你可能想做的事情是这样的:
"A" in a # True
如果你出于某种原因必须使用any()
,可以试试:
any(item == "A" for item in a)
这种方法的好处是可以轻松进行不精确的比较(in
只会进行精确比较)。例如:
any(item.lower() == "a" for item in a) # case-insensitive
any("a" in item.lower() for item in a) # substring match
any(item.lower().startswith("a") for item in a)
27
问题在于,any()
这个函数只要有一个元素是 True
,就会返回 True
。所以你的代码会一直循环,直到答案等于 months_list 中的所有字符串,这可能不是你想要的结果。这里有一种用法,如果答案和 months_list 中的任何一个字符串匹配,就可以停止或跳出循环:
months_list = ["January", "February", "March", "April", "May", "June", "July"]
while True:
answer = raw_input("Month? ")
if any(item.lower() == answer.lower() for item in months_list):
break
print("Sorry, didn't recognize your answer, try again")
正如其他人提到的,虽然使用 Python 的 in
操作符会更简单,但那样仍然会进行线性搜索,也就是 O(n) 的复杂度。所以更好的(更快的)方法是使用一个小写的 month_names
集合,这样就可以利用哈希表的查找,复杂度是 O(1),而不是线性搜索:
months = set(month.lower() for month in ("January", "February", "March", "April",
"May", "June", "July"))
while True:
answer = raw_input("Month? ")
if answer.lower() in months:
break
print("Sorry, didn't recognize your answer, try again")
进一步优化
根据字符串的特点和你比较它们的原因,使用字符串的 casefold()
方法可能会比 lower()
更好,这样可以进行不区分大小写的字符串比较。