Python 的 any() 函数有什么作用?
Python 的 any() 是内置函数之一。它接受一个 可迭代对象,如 列表或 元组,如果该可迭代对象中至少有一个值为 truthy(真值),则返回 True。当对象通过 bool() 转为布尔值为 True 时,称其为 truthy。若所有值均为 falsy(假值),any() 返回 False:
print(any([True, False, False, True]))
print(any([False, False, False, False]))
print(any([0, 0, 5, 0]))
True
False
True
可迭代对象可以包含布尔值或其他对象,因为所有对象在转换为布尔值时都会被评估为 True 或 False。在第三个示例中,列表包含四个整数。整数 0 为假值,但所有非零数字都为真值。若想更好地理解真值与假值的区别,请阅读这篇关于 Python 逻辑运算符的博文。
如果可迭代对象为空,any() 返回 False,因为空的可迭代对象中没有真值:
print(any([]))
False
下一节将更深入探讨 any() 的工作原理。
any() 的工作原理
内置函数 any() 的参数可以是任意可迭代对象。可迭代对象是指 Python 可以对其进行循环遍历的任何数据结构。
考虑以下元组:
an_iterable = ("", 0.0, "DataCamp", False, [])
该元组包含多种类型的对象。其中有几项是假值:
- 空字符串
"" - 浮点数
0.0 - 布尔值
False - 空列表
[]
这些对象之所以为假值,是因为将它们传给 bool() 时会被评估为 False。
非空字符串 "DataCamp" 为真值。
检查是否至少存在一个真值的直接方式是使用 for 循环:
def check_if_contains_truthy(data):
output = False
for item in data:
if item:
output = True
return output
print(check_if_contains_truthy(an_iterable))
True
不过,这样效率不高,因为该函数只需判断是否存在至少一个真值。一旦找到一个真值,便无需继续检查其余元素。可以修改函数,使其在找到第一个真值时立即返回:
def check_if_contains_truthy(data):
for item in data:
if item:
return True
return False
print(check_if_contains_truthy(an_iterable))
True
return 语句会终止函数执行。因此,当函数发现第一个真值时,它返回 True,并不再继续遍历。只有当 for 循环遍历完整个可迭代对象且未发现真值时,函数才会返回 False。
内置函数 any() 采取了类似的模式:在遇到第一个真值时短路返回。这种惰性求值避免了不必要的操作,从而提升性能。Python 的 any() 是上述函数的更高效版本。可通过 timeit 模块中的 timeit() 函数来验证这种效率提升,timeit() 用于计量 Python 执行某段语句所需的时间:
from timeit import timeit
print("Execution time for 'check_if_contains_truthy()'")
print(
timeit(
"check_if_contains_truthy(an_iterable)",
number=10_000_000,
globals=globals(),
)
)
print("Execution time for 'any()'")
print(
timeit(
"any(an_iterable)",
number=10_000_000,
globals=globals(),
)
)
Execution time for 'check_if_contains_truthy()'
0.6335119580035098
Execution time for 'any()'
0.39488654200249584
timeit() 的第一个参数是包含待执行语句的字符串。第二个参数指定运行次数。在此示例中,两段语句均执行 10,000,000 次以获得有意义的计时结果。最后一个参数将全局变量传递给 timeit() 函数。
Python 的 any() 比 check_if_contains_truthy() 更快。与使用 for 循环相比,使用 any() 判断可迭代对象中是否至少有一个真值,更加 Pythonic 且高效。
any() 的使用场景
下面来看一些 Python any() 的使用场景。
检查是否至少有一个用户输入有效
设想用列表或元组收集了一组用户输入。程序可能需要检查是否至少有一个输入是有效的,例如是否为非空字符串:
user_inputs = ["", "10.99", ""]
if any(user_inputs):
print("At least one valid input present")
# Rest of code...
else:
print("There are no valid inputs")
At least one valid input present
由于其中有一个字符串非空,any() 返回 True,并执行 if 分支中的代码。
检查是否至少存在一个文件
内置函数 any() 可用于检查文件名列表中是否至少有一个文件在某目录下存在:
from pathlib import Path
files = ["article.md", "use_any.py", "scratch.py", "test_file.txt"]
cwd = Path.cwd()
# Create a test file to test code
Path("test_file.txt").write_text("This is a test file")
if any(Path(file).exists() for file in files):
print("At least one of the files exists")
# Rest of code…
else:
print("None of the files exist")
At least one of the files exists
代码使用 pathlib 模块与 Path.cwd() 获取当前工作目录。它在工作目录中创建名为 test_file.txt 的文件,以便轻松测试这段代码。随后使用 Python 的 any() 来检查在当前工作目录下是否至少存在一个给定的文件名。
从可迭代对象中过滤条目
内置函数 any() 也可与 生成器表达式配合使用,从可迭代对象中过滤条目。在此示例中,any() 会在一个由字典组成的列表中寻找是否存在至少一条年龄小于 18 的记录:
records = [
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
There's at least one minor.
生成器表达式会根据每个字典中 "age" 键对应的值返回 True 或 False。由于生成器表达式是可迭代的,因此可以在 any() 中使用。
再谈 Python 中 any() 的惰性求值
上一个示例也可以用来说明 any() 的惰性求值。考虑如下对字典列表的修改:
records = [
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
{"name": "Jill"},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
There's at least one minor.
records 中的第四个字典没有键 "age"。然而,在为该条目尝试获取 "age" 对应的值时,代码并未抛出错误,因为 any() 在此之前就已找到一个真值,从而短路返回。
如果缺少 "age" 键的字典出现在任何年龄小于 18 的条目之前,代码将引发 KeyError:
records = [
{"name": "Jill"},
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
Traceback (most recent call last):
...
if any(record["age"] < 18 for record in records):
~~~~~^^^^^^
KeyError: 'age'
该示例旨在演示使用 Python 的 any() 时的短路行为。如果不希望对缺少 "age" 键的条目抛出异常,可以采用另一种方式:使用字典方法 .get() 并提供默认值,而不是用方括号访问字典键。若默认行为是假定没有年龄的条目不是未成年人,则可以将 if 语句替换为以下版本:
if any(record.get("age", 18) < 18 for record in records):
# ...
如果代码应假定任何没有年龄的条目都是未成年人,则默认值需要小于 18。
Python:any() 与 all() 的对比
Python 的 any() 有一个配套函数—— all()。该内置函数同样接受可迭代对象,如果所有元素都为真值,则返回 True。
回到本教程前面的用户输入校验示例。若应用仅要求至少一个有效输入,any() 很有用;而若要求所有用户输入均有效,则可使用 all():
user_inputs = ["", "10.99", ""]
if any(user_inputs):
print("At least one valid input present")
# Rest of code...
else:
print("There are no valid inputs")
if all(user_inputs):
print("All inputs are valid")
# Rest of code...
else:
print("Not all inputs are valid")
At least one valid input present
Not all inputs are valid
然而,如果用户输入中的所有字符串都非空,all() 将返回 True:
user_inputs = ["5.99", "10.99", "19.99"]
# …
At least one valid input present
All inputs are valid
与 any() 类似,内置函数 all() 也采用惰性求值。在遇到第一个假值时会短路返回。
结论
Python 的 any() 用于判断可迭代对象中的任一元素是否为真值。若可迭代对象中至少有一个元素为 True,或转换为布尔值后为 True,函数便返回 True。虽然使用循环也能实现相同的结果,但该内置函数提供了更易读且更高效的解决方案。
我在马耳他大学完成了本科阶段的物理与数学学习。随后前往伦敦,并在帝国理工学院取得物理学博士学位,研究用于成像人类视网膜的新型光学技术。现在,我专注于撰写与传播 Python 相关内容,并教授 Python。

在 Python 程序中,一个常见需求是检查某个数据结构中是否至少有一个元素为
True。虽然可以写一个循环来遍历可迭代对象并检查每个元素是否为
True或False,但 Python 的any()函数提供了更高效、更 Pythonic 的方式来实现这一点。本教程将介绍 Python 的内置函数
any(),并通过多个示例展示其用法与应用场景。