Python 的内置函数不需要导入即可使用。sum()、enumerate()、zip()、sorted() 等函数看似基础,却直接影响代码是否简洁、清晰且符合 Python 的惯用写法。掌握它们的关键并不是背诵函数列表,而是知道每类函数解决什么问题,以及哪些边界容易踩坑。
数值计算与数据类型转换
处理数值时,优先考虑表达意图明确的内置函数:
abs(x)返回绝对值。round(x, ndigits)执行舍入。min()和max()查找最小值与最大值。sum(iterable, start=0)汇总可迭代对象中的数值。pow(x, y)计算幂,传入第三个参数时可执行模幂运算。
prices = [19.9, 8.5, 12.0]
print(sum(prices))
print(round(sum(prices), 2))
print(min(prices), max(prices))
print(abs(-42))
print(pow(2, 10))
print(pow(2, 10, 1000))
类型转换函数同时承担数据校验入口的角色。int()、float()、str()、bool()、list()、tuple()、set() 和 dict() 可以把外部数据转换成程序期望的形式。
port_text = "8080"
port = int(port_text)
unique_tags = set(["python", "api", "python"])
ordered_tags = sorted(unique_tags)
print(port, type(port).__name__)
print(ordered_tags)
需要注意,bool("False") 的结果是 True,因为任何非空字符串都是真值。解析配置中的布尔值时,应显式比较文本,而不是直接调用 bool()。
def parse_bool(value: str) -> bool:
normalized = value.strip().lower()
if normalized in {"true", "1", "yes", "on"}:
return True
if normalized in {"false", "0", "no", "off"}:
return False
raise ValueError(f"无法识别的布尔值:{value!r}")
print(parse_bool("yes"))
print(parse_bool("OFF"))
让迭代代码更像 Python
很多冗长循环都可以由内置函数直接表达。enumerate() 同时提供索引和值,避免手动维护计数器;zip() 按位置组合多个可迭代对象;sorted() 返回新列表,而 reversed() 提供反向迭代器。
names = ["Ada", "Linus", "Grace"]
scores = [98, 91, 96]
for position, (name, score) in enumerate(zip(names, scores), start=1):
print(f"{position}. {name}: {score}")
ranking = sorted(
zip(names, scores),
key=lambda item: item[1],
reverse=True,
)
print(ranking)
all() 和 any() 特别适合表达批量条件:
statuses = [200, 204, 201]
all_succeeded = all(200 <= status < 300 for status in statuses)
has_server_error = any(status >= 500 for status in statuses)
print(all_succeeded)
print(has_server_error)
这里使用生成器表达式,没有预先创建完整的布尔列表。all() 遇到第一个假值就停止,any() 遇到第一个真值就停止,因此它们既清楚又支持短路求值。
还要留意 zip() 的默认行为:它会在最短的输入耗尽时停止。如果不同长度意味着数据错误,在支持 strict 参数的 Python 版本中可以使用 zip(a, b, strict=True),让长度不一致立即抛出异常。
从输入到报表:一个可运行示例
下面的脚本把类型转换、排序、聚合、枚举和输出组合成一个小型成绩报表。将内容保存为 report.py 后即可运行;也可以直接复制到 Python 解释器中。
from pathlib import Path
def build_report(rows: list[str]) -> str:
records = []
for line_number, row in enumerate(rows, start=1):
name, score_text = map(str.strip, row.split(",", maxsplit=1))
score = float(score_text)
records.append({"name": name, "score": score, "line": line_number})
ranked = sorted(records, key=lambda item: item["score"], reverse=True)
average = sum(item["score"] for item in ranked) / len(ranked)
output = [f"人数: {len(ranked)}", f"平均分: {average:.2f}"]
for rank, item in enumerate(ranked, start=1):
output.append(f"{rank}. {item['name']}: {item['score']:.1f}")
return "\n".join(output)
def main() -> None:
source = Path("scores.csv")
if source.exists():
rows = source.read_text(encoding="utf-8").splitlines()
else:
rows = ["Ada, 98", "Linus, 91", "Grace, 96"]
if not rows:
raise ValueError("没有可处理的成绩记录")
print(build_report(rows))
if __name__ == "__main__":
main()
运行命令:
python report.py
这个例子中的函数各自承担明确职责:map() 清理拆分后的字段,float() 完成类型转换,sorted() 生成排名,sum() 计算总分,len() 提供记录数量,enumerate() 生成名次,print() 输出最终结果。
实际项目还应捕获格式错误和非法分数。例如,row.split() 可能因为缺少逗号而失败,float() 也可能抛出 ValueError。不要为了“让程序继续运行”而捕获所有异常;应提供行号和原始数据,让调用方能定位问题。
I/O 函数的边界
print() 适合脚本输出、交互式调试和简单命令行程序。生产服务需要日志级别、时间戳和结构化字段时,应改用 logging 模块。
input() 始终返回字符串,因此数值输入必须显式转换:
age_text = input("请输入年龄:")
try:
age = int(age_text)
except ValueError:
raise SystemExit("年龄必须是整数")
print(f"明年你将是 {age + 1} 岁")
不要使用 eval(input()) 解析用户数据。eval() 会执行任意 Python 表达式,无法信任的输入可能直接变成代码执行漏洞。JSON 数据应使用 json.loads(),Python 字面量确有必要时可考虑 ast.literal_eval()。
采用时检查这几件事
内置函数的价值在于缩短“机制代码”,让业务意图更明显。落地时可以检查以下几点:
- 循环计数是否可以改为
enumerate()。 - 并行遍历是否可以改为
zip(),以及是否需要检查长度一致性。 - 批量判断是否适合
all()或any()。 - 排序逻辑是否可以集中到
sorted(..., key=...)。 - 外部输入是否在边界处完成类型转换并处理异常。
- 是否误把变量命名为
list、str、sum或input,从而遮蔽同名内置函数。 - 数据量较大时,是否使用生成器表达式避免不必要的中间列表。
不必把每个循环都压缩成一行。内置函数应该减少认知负担;当嵌套调用开始掩盖业务规则时,拆成具名函数和中间变量通常更容易维护。