前言
Python 的内置函数(built-in function)是解释器启动时就注入命名空间的一批函数,不需要任何import就能调用。数量不多,每个 3.x 版本也就几十个,但覆盖了输入输出、类型转换、判断检查、迭代聚合、数学运算这些最常见的动作。
一个普遍的误解是"内置函数很多,要背下来"。实际上日常代码里反复出现的也就二十来个,剩下的多数有更清晰的替代写法:map+filter+lambda往往不如一个列表推导式好读;__import__()几乎永远应该写成import语句。本文按功能分组梳理常用内置函数,给出可运行示例,并明确哪几个应该少用。
本文面向 Python 3(3.8 及以上均可运行)。Python 2 的print语句、raw_input()、xrange()在 Python 3 中都已不复存在(print变成函数,raw_input改名input,xrange被range取代),Python 2.7 自 2020 年 1 月 1 日起停止维护,本文一律按 Python 3 写。
一、内置函数存放在哪里
它们都在builtins模块里,解释器把该模块的所有公开名字预先放进每个作用域的全局命名空间,所以你不用 import 就能用。
# 适用于 Python 3.8+
import builtins
names = sorted(n for n in dir(builtins) if not n.startswith('_'))
print(len(names))
print(names)
因为只是普通名字,你完全可以用自己的变量覆盖它们——这既是灵活性,也是坑(详见常见坑点)。另外help()虽属内置命名空间,但它其实是site模块在启动时添加的,用python -S启动后就调用不到。
二、输入输出与表示
print | print(*objects, sep=' ', end='\n', file=None, flush=False) | None |
input | input(prompt, /) | str(永远是字符串) |
open | open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) | 文件对象 |
format | format(value, format_spec='', /) | str |
repr | repr(object, /) | str(面向调试的可读表示) |
# 适用于 Python 3.8+
print("a", "b", sep="-", end="!\n") # a-b!
name = input("请输入名字: ") # 返回值永远是 str
print(format(3.14159, ".2f")) # 3.14
print(repr("a\tb")) # 'a\tb'
print(str("a\tb")) # 制表符被真实展开
input()永远返回字符串,需要数字必须自己转换;repr()与str()的区别在于前者尽量给出"能重新构造该对象"的表示,调试打印容器时用repr()(或!r格式化)信息更完整。
三、类型转换与构造
int/float/str/list/tuple/dict/set/bytes/bool既是类型也是可调用对象,调用它们就是构造新对象。
# 适用于 Python 3.8+
print(int("2a", 16)) # 42,第二参数是进制
print(list("abc")) # ['a', 'b', 'c']
print(tuple([1, 2])) # (1, 2)
print(set([1, 1, 2])) # {1, 2}
print(bool(0), bool("")) # False False
print(str(12) + "x") # 12x
# int("abc") 会抛 ValueError
# int(None) 会抛 TypeError
注意int()对浮点是截断而非四舍五入:int(3.99)得3;要四舍五入用round(3.99)(但注意银行家舍入)。
四、判断与检查
isinstance(obj, classinfo) | 类型判断 | 考虑继承,推荐首选 |
issubclass(cls, classinfo) | 继承判断 | 只看类 |
callable(obj) | 能否调用 | 有__call__即可 |
hasattr(obj, name) | 属性是否存在 | 会触发属性访问 |
getattr(obj, name, default) | 取属性 | 带默认值更安全 |
all(iterable)/any(iterable) | 全体 / 任一为真 | 空序列时all为True、any为False |
# 适用于 Python 3.8+
print(isinstance(True, int)) # True,bool 是 int 的子类
print(all([]), any([])) # True False
print(callable(len), callable(1)) # True False
class C:
x = 1
c = C()
print(getattr(c, "y", "默认")) # 默认
print(hasattr(c, "x")) # True
all()和any()都是短路的:any遇到第一个真值就停,all遇到第一个假值就停,因此它们可以配合生成器做惰性判断。
五、迭代、序列与聚合
range(stop)/range(start, stop[, step]) | range对象 | 是 |
enumerate(iterable, start=0) | 迭代器 | 是 |
zip(*iterables, strict=False) | 迭代器 | 是 |
map(function, iterable, *iterables) | 迭代器 | 是 |
filter(function, iterable) | 迭代器 | 是 |
sorted(iterable, *, key=None, reverse=False) | 新list | 否 |
sum(iterable, start=0) | 数值 | 否 |
# 适用于 Python 3.8+
nums = [3, 1, 4, 1, 5, 9]
print(sorted(nums)) # [1, 1, 3, 4, 5, 9]
print(sorted(set(nums), reverse=True)) # [9, 5, 4, 3, 1]
print(sum(nums), max(nums), min(nums)) # 23 9 1
pairs = [("b", 2), ("a", 1)]
print(max(pairs, key=lambda p: p[1])) # ('b', 2)
for i, ch in enumerate("abc", start=1):
print(i, ch)
print(list(reversed("abc"))) # ['c', 'b', 'a']
zip()的strict参数需要3.10 及以上;map()的strict参数需要3.14 及以上,写兼容 3.8 的代码时不要使用。
六、数学与进制
round(number, ndigits=None) | 银行家舍入(round half to even) |
divmod(a, b) | 返回(a // b, a % b) |
pow(base, exp, mod=None) | 三参数时做模幂,比(base ** exp) % mod高效 |
# 适用于 Python 3.8+
print(round(2.5), round(3.5)) # 2 4,银行家舍入
print(divmod(-7, 3)) # (-3, 2)
print(pow(2, 10, 1000)) # 24,等价于 1024 % 1000
print(bin(10), oct(10), hex(10)) # 0b1010 0o12 0xa
print(ord("中"), chr(20013)) # 20013 中
常见坑点
坑 1:用变量名覆盖内置函数。
❌list = [1, 2, 3]之后再想list("abc")就报TypeError,因为list已被绑成列表。
✅ 换个名字,如items = [1, 2, 3]。同理不要用id、type、sum、format、input当变量名。
坑 2:以为input()返回数字。
❌age = input("年龄: "); print(age + 1)—— 字符串加整数抛TypeError。
✅age = int(input("年龄: ")),并做好ValueError的兜底。
坑 3:sorted()返回None?
❌nums = nums.sort()——nums变None,后面全崩。
✅nums = sorted(nums)或nums.sort()(后者原地排序,不要接返回值)。
坑 4:sorted()把key当位置参数。
❌sorted(data, lambda x: x[1])—— 抛TypeError,key和reverse是仅关键字参数。
✅sorted(data, key=lambda x: x[1])。
坑 5:对迭代器求两次值。
❌
nums = [1, 2, 3]
it = filter(lambda x: x % 2, nums)
print(sum(it)) # 2
print(list(it)) # [],已被消费完
✅ 需要重复用就先lst = list(it),之后都用lst。
坑 6:all([])与any([])想当然。
❌ 以为空序列都返回False。
✅all([])是True(无假值即全真),any([])是False(无真值即全假),这是数学上的约定。
坑 7:max()/min()对空序列直接调用。
❌max([])—— 抛ValueError: max() arg is an empty sequence。
✅max([], default=None)(default仅在单个可迭代参数形式下可用)。
坑 8:str()和repr()混用做调试输出。
❌ 打印嵌套结构时用print(str(nested)),字符串值看不出引号,"1"与1分不清。
✅ 用print(repr(nested))或 f-string 里的{nested!r}。
总结
| 输入输出 | print、input、open | input返回str;open要写encoding |
| 类型转换 | int、float、str、list、set、dict | int()是截断不是四舍五入 |
| 判断检查 | isinstance、hasattr、getattr、all、any | 优先isinstance而非type |
| 迭代序列 | len、range、enumerate、zip、sorted | 惰性的那几个返回迭代器 |
| 数学进制 | abs、round、divmod、pow、hex | round是银行家舍入 |
真正要记的其实就一句话:惰性函数返回迭代器只能消费一次,原地方法(list.sort)返回None,而sorted返回新列表。拿不准签名时,在解释器里help(函数名)一敲,参数名和默认值都清清楚楚,比任何清单都可靠。