别只会 len 和 print:用一组小测吃透 Python 内置函数

2026-07-21 20 预计阅读时间: 1 分钟
来源: realpython.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

Python 的内置函数不需要导入即可调用,覆盖数值计算、类型转换、迭代处理和输入输出等常见任务。真正需要掌握的并不是函数名,而是它们的返回类型、边界行为,以及什么时候应该用内置函数替代手写循环。

数值与类型:结果可能和直觉不同

先看三道题,尝试在运行代码前判断输出:

print(round(2.5), round(3.5))
print(bool([]), bool([0]))
print(int("101", 2))

答案是:

2 4
False True
5

round() 在恰好位于两个整数中间时,会选择偶数方向的结果。因此 2.5 得到 23.5 得到 4。浮点数还存在二进制表示误差,所以涉及金额或严格小数规则时,应考虑 decimal.Decimal,不要仅依赖 round()

bool() 判断的是对象的真值。空容器、零和 None 通常为假;非空容器为真,其中保存的元素是不是零并不影响容器本身的真值。

int() 不只用于把十进制字符串转成整数。第二个参数可以指定进制,例如 int("101", 2) 会把二进制字符串解析为十进制整数 5

类型转换失败时通常会抛出异常。面对外部输入,可以明确处理错误:

def parse_port(raw: str) -> int:
    try:
        port = int(raw)
    except ValueError as exc:
        raise ValueError(f"端口必须是整数:{raw!r}") from exc

    if not 1 <= port <= 65535:
        raise ValueError("端口必须位于 1 到 65535 之间")
    return port

print(parse_port("8080"))

迭代器:一行代码背后的消费行为

sum()min()max()sorted()any()all() 都能处理可迭代对象,但它们并不具有相同的执行特征。

numbers = [7, 2, 9, 4]

print(sum(numbers))
print(min(numbers), max(numbers))
print(sorted(numbers))
print(numbers)

sorted() 返回新列表,不会修改原对象;列表的 .sort() 方法则会原地排序并返回 None。如果后续代码仍依赖原始顺序,sorted() 通常更稳妥。

any()all() 会短路求值。any() 找到第一个真值就停止,all() 找到第一个假值就停止:

def check(value: int) -> bool:
    print(f"检查 {value}")
    return value > 3

print(any(check(x) for x in [1, 2, 5, 8]))

程序不会检查 8,因为处理到 5 时结果已经确定。这个特性适合存在昂贵计算的校验流程,但生成器中的副作用也可能因此只执行一部分。

另一个容易忽略的边界是空输入:

print(sum([]))       # 0
print(any([]))       # False
print(all([]))       # True

all([])True 源于逻辑上的“空真”。如果业务规则要求“至少有一项并且全部通过”,必须额外检查集合是否非空:

checks = []
passed = bool(checks) and all(checks)
print(passed)  # False

把多个序列放进同一个循环

enumerate()zip() 可以消除大量手写索引,让循环直接表达意图:

names = ["Ada", "Linus", "Guido"]
scores = [95, 88, 91]

for rank, (name, score) in enumerate(zip(names, scores), start=1):
    print(f"{rank}. {name}: {score}")

不过,zip() 默认会在最短序列结束时停止。长度不一致可能意味着数据错误时,可以在支持 strict 参数的 Python 版本中这样实践:

names = ["Ada", "Linus"]
scores = [95]

try:
    for name, score in zip(names, scores, strict=True):
        print(name, score)
except ValueError as exc:
    print(f"数据长度不一致:{exc}")

map()filter() 也会返回惰性迭代器。简单转换经常用列表推导式更易读;需要流式处理大量数据时,保留迭代器则可以减少中间列表占用的内存。

可复制运行的综合小测

下面的脚本只使用标准 Python,可以保存为 builtins_quiz.py 后运行。它覆盖类型转换、排序、聚合、短路判断、序列组合和安全输入处理。

from collections.abc import Callable

Question = tuple[str, Callable[[], object], object]

questions: list[Question] = [
    ("二进制 111 的十进制值", lambda: int("111", 2), 7),
    ("绝对值", lambda: abs(-12), 12),
    ("按长度排序", lambda: sorted(["pear", "fig", "apple"], key=len),
     ["fig", "pear", "apple"]),
    ("是否存在偶数", lambda: any(x % 2 == 0 for x in [1, 3, 6]), True),
    ("是否全部为正数", lambda: all(x > 0 for x in [2, 5, 9]), True),
    ("带起始值的求和", lambda: sum([2, 3, 4], start=10), 19),
]

score = 0
for index, (label, operation, expected) in enumerate(questions, start=1):
    actual = operation()
    passed = actual == expected
    score += int(passed)
    print(f"{index}. {label}: {actual!r} - {'通过' if passed else '失败'}")

print(f"得分:{score}/{len(questions)}")

运行命令:

python builtins_quiz.py

可以继续给 questions 增加案例,例如测试 max(..., key=...)reversed()format()。每个案例同时记录预期结果,比只阅读函数列表更容易暴露理解偏差。

I/O 与命名陷阱

input() 总是返回字符串,即使用户输入的是数字。可以这样实践一个可重复提示的整数读取函数:

def read_age() -> int:
    while True:
        raw = input("请输入年龄:").strip()
        try:
            age = int(raw)
        except ValueError:
            print("请输入整数。")
            continue

        if 0 <= age <= 150:
            return age
        print("年龄必须位于 0 到 150 之间。")

print(f"记录的年龄:{read_age()}")

同时要避免把变量命名为 liststrsummaxinput。这些名称会遮蔽同名内置函数:

sum = 42
# sum([1, 2, 3])  # TypeError: 'int' object is not callable

如果在交互环境中不慎发生遮蔽,可以删除变量恢复名称解析:

del sum
print(sum([1, 2, 3]))

在正式代码中,直接使用 totalitemstext 等更具体的变量名更清晰。

采用时检查这几件事

使用内置函数前,可以快速确认四个问题:输入是一次性迭代器还是可重复遍历的容器;函数返回新对象还是原地修改;空输入会得到什么;转换失败会抛出哪种异常。

优先选择能准确表达意图的内置函数,但不要为了压缩行数牺牲错误处理。sum(values) 通常比手写累加循环清楚,而外部输入的 int(raw) 则应配合异常处理和业务范围校验。理解这些边界后,内置函数才不只是语法捷径,而是可靠、可读的基础工具。


相关推荐