首页
/ CPython 内置函数全景指南:从 abs 到 zip,深入 Python 解释器的 builtins 机制与 3.15 新特性

CPython 内置函数全景指南:从 abs 到 zip,深入 Python 解释器的 builtins 机制与 3.15 新特性

2026-09-07 15:00:31作者:邵娇湘

本篇基于 CPython 官方文档 Doc/library/functions.rst 系统梳理 Python 解释器自带的全部内置函数(built-in functions):它们无需导入、始终可用,是 Python 编程的地基。文章完整覆盖内置函数清单、类型构造器、动态执行(compile/eval/exec)、反射与自省、迭代工具、open() 文件 I/O 的每个参数,并结合当前仓库源码(Python/bltinmodule.cObjects/dictobject.c)说明 3.15 新引入的 frozendictsentinel 等特性的实现落点,读完后你可以准确使用每一个内置函数并理解其在 CPython 内部的工作方式。

一、内置函数总览

Python 解释器将一批函数和类型"内建"于 builtins 模块中,随时可用。文档按字母序列出了完整清单:

类别 内置函数
转换与构造 absasciibinboolbytearraybytescomplexdictfloatfrozendictfrozensethexintlistmemoryviewoctrangereprroundsetslicestrsupertupletypeobject
迭代与转换 aiteranextallanyenumeratefiltermapmaxminnextreversedsortedsumzipiterlen
动态执行 compileevalexec__import__
反射与自省 callabledelattrdirgetattrglobalshasattrhashidinputisinstanceissubclasslocalssetattrvars
文件与调试 openprintbreakpointhelp
属性与装饰器 propertyclassmethodstaticmethodformatpowdivmodchrord
3.15 新增 frozendict(不可变字典)、sentinel(哨兵对象)

其中 dictlistsetfrozensettuplerangestrbytesbytearraymemoryviewfrozendict 本质是"类"而非纯函数——文档在内置函数表中列出它们,是因为其构造函数入口就在这里,完整语义参见数据类型的专页。

在 CPython 源码中,这些函数的 C 实现集中在 Python/bltinmodule.c(含自动生成的 Python/clinic/bltinmodule.c.h 参数解析代码),该文件负责把 C 函数注册进 builtins 模块的符号表。

二、数值与类型构造器

2.1 int:多进制解析与转换优先级

int() 支持三种形态:int() 返回 0;int(123.45) 按"向零截断"转为 123;int(string, base)base(2–36,或 0 自动识别前缀)解析字符串/bytes/bytearray:

>>> int('123')
123
>>> int('   -12_345\n')
-12345
>>> int('FACE', 16)
64206
>>> int('0xface', 0)
64206
>>> int('01110011', base=2)
115

要点:

  • 字符串可含 +/- 前缀、前导零、空白,数字间允许单下划线分组;
  • base=0 时按字面量规则依 0b/0o/0x 前缀判定进制,且禁止前导零int('010', 0) 非法,而 int('010')int('010', 8) 合法);
  • 对任意对象 xint(x) 委托 x.__int__(),若未定义则回退 x.__index__();3.14 起不再回退 __trunc__
  • 3.11 起整数↔字符串转换受 sys.set_int_max_str_digits() 长度限制约束(防 DoS 攻击),超限抛 ValueError

float()complex() 同理:字符串输入必须匹配文档给出的 floatvalue/complexvalue 文法(支持 inf/nan/Infinity,大小写不敏感);对象参数依次回退 __float____index__(float)或 __complex____float____index__(complex)。complex 还接受实部/虚部两个参数,如 complex(-1.23, 4.5)(-1.23+4.5j)

2.2 二进制串转换:bin / hex / oct / float.hex

binhexoct 要求参数是 int 或定义了 __index__ 的对象,返回值是带前缀的合法 Python 表达式(bin(3)'0b11'hex(-42)'-0x2a')。需要自定义前缀/大小写时用 format

>>> format(255, '#x'), format(255, 'x'), format(255, 'X')
('0xff', 'ff', 'FF')

浮点数的十六进制表示则用 float.hex() 方法,而非 hex()

2.3 frozendict:3.15 的不可变字典

frozendict 是 3.15 新增的内置类,构造签名与 dict 一致:

frozendict(**kwargs)
frozendict(mapping, /, **kwargs)
frozendict(iterable, /, **kwargs)

从源码结构看,它复用 dict 的核心实现:Objects/dictobject.c 中定义了 PyFrozenDict_Typefrozendict_new(约 L139),内部通过 frozendict_does_not_support() 宏在赋值、删除操作时统一抛出 TypeError: frozendict object does not support "assignment"/"deletion"frozendict_length(约 L3793)等函数则与 dict 共享长度/遍历路径。内部头文件 Include/internal/pycore_dict.h 声明了 PyFrozenDict_Type 供解释器内部使用。源码中多条注释(如 gh-151722 相关)表明 frozendict 刻意不被 GC 追踪——因为它不可变,无需参与循环引用收集。

frozendict 的实战价值:可作为字典键、以及跨线程共享配置的只读快照。eval/execglobals 参数与 typedict 参数从 3.15 起也接受 frozendict,见下文。

2.4 bytes / bytearray:可变与不可变字节序列

两者构造参数相同:可传字符串(必须同时给 encoding,可选 errors,经 str.encode 转换)、整数(以空字节初始化该大小的数组)、buffer 接口对象,或 0–255 整数的可迭代对象。bytearray 可变、支持可变序列的全部常规方法;bytes 是其不可变版本,也可写字面量 b'...'

三、动态代码执行:compile、eval、exec

3.1 compile:源码 → 代码对象/AST

compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1, *, module=None)
  • source:普通字符串、字节串或 AST 对象;
  • mode'exec'(语句序列)、'eval'(单一表达式)、'single'(单条交互语句,非 None 的表达式结果会被打印);
  • optimize-1 跟随解释器的 -O 级别;0 不优化(__debug__ 为真)、1 移除 assert、2 连 docstring 也移除;
  • flags/dont_inherit:控制编译器选项与 __future__ 特性继承;3.8 起可用 ast.PyCF_ALLOW_TOP_LEVEL_AWAIT 允许顶层 await;
  • module(3.15 新增):指定模块名,用于按模块名过滤语法警告。

注意两点:'single'/'eval' 模式下多行字符串必须以换行结尾;用极大字符串编译 AST 可能因 AST 编译器栈深限制而崩溃解释器。解析纯 AST 应使用 ast.parse。该函数触发审计事件 compile(参数为 source 与 filename)。

3.2 eval 与 exec:带审计的动态执行

eval(source, /, globals=None, locals=None)
exec(source, /, globals=None, locals=None, *, closure=None)

文档对二者都给出醒目警告:它们执行任意代码,传入不受信任的用户输入会造成安全漏洞。关键行为细节:

  • globals 中无 __builtins__ 键,会自动插入 builtins 模块字典的引用;覆写 __builtins__ 可限制可用名字,但文档明确强调这不是安全机制
  • evalsource 是"表达式列表",eval("1, 2")(1, 2);可执行 code object(若该对象以 'exec' 模式编译,返回 None);
  • exec 支持 closure(3.11 新增):当 code object 含自由变量时,传入 cellvars 元组,长度必须与 co_freevars 一致;
  • 3.13 起 globals/locals 可用关键字传参,默认 locals 语义与 locals() 内置函数一致;3.15 起 globals 可为 frozendict
  • 两者都触发 exec 审计事件(参数为 code object)。

典型用法:

>>> x = 1
>>> eval('x+1')
2

四、反射与自省:getattr 家族、dir、type

4.1 getattr / setattr / delattr / hasattr

四件套把属性操作参数化:getattr(x, 'foobar')x.foobarsetattr(x, 'foobar', 123)x.foobar = 123delattr(x, 'foobar')del x.foobarhasattr 等价于"调用 getattr 看是否抛 AttributeError"。两个重要注意点:

  • name 不必是合法 Python 标识符(除非对象通过自定义 __getattribute____slots__ 强制);非标识符属性无法用点语法访问,但可经 getattr 取到;
  • 私有名改写(双下划线前缀)发生在编译期,用 getattr 取/设私有属性必须手动改写名字。

4.2 dir 与 vars

dir() 无参返回当前局部作用域的名字列表;有参时优先调用对象的 __dir__,否则尽量从 __dict__ 和类型对象收集。它按对象类型给出"最相关而非最完整"的名字:模块给模块属性;类递归包含基类属性;普通实例含实例、类及基类链属性。结果按字母序排序,且文档声明其细节行为可能随版本变化(例如元类属性不会出现在类的 dir 结果中)。

vars(object) 返回带 __dict__ 的对象(模块、类、实例)的 __dict__;无参时行为同 locals()。注意:类的 __dict__types.MappingProxyType(只读代理),直接更新会失败;对象若用 __slots__ 而无 __dict__varsTypeError

4.3 id、hash、len

  • id() 返回对象生命周期内唯一恒定的整数;实现细节上就是对象的内存地址,并触发 builtins.id 审计事件;
  • hash() 返回哈希整数,用于字典键的快速比较;相等的数值拥有相同哈希(hash(1) == hash(1.0));自定义 __hash__ 的返回值会被按主机位宽截断;
  • len() 对长于 sys.maxsize 的长度抛 OverflowError(例如 range(2 ** 100))。

4.4 type:查看类型与动态建类

type(obj) 返回类型对象,一般即 obj.__class__;类型判断推荐 isinstance()(考虑子类)。三参数形式 type(name, bases, dict) 是动态版 class 语句:

>>> X = type('X', (), dict(a=1))

它不调用元类 __prepare__——需要元类机制时应使用 types.new_class。3.15 起 dict 参数可接受 frozendict

五、迭代工具:map、filter、zip、enumerate 与 3.14 的 strict

5.1 map:多可迭代并行映射

map(function, iterable, /, *iterables, strict=False)

多可迭代时按并行取元组应用 function,默认最短者耗尽即止;3.14 新增 strict=True:任一可迭代先耗尽时抛 ValueError 而非静默截断。输入已组织成元组的场景可用 itertools.starmap

5.2 zip:行变列,以及 strict 参数

zip 并行迭代多个可迭代对象,第 i 个元组含每个输入的第 i 个元素——相当于矩阵转置。文档给出了处理不等长输入的三种策略:

>>> list(zip(range(3), ['fee', 'fi', 'fo', 'fum']))
[(0, 'fee'), (1, 'fi'), (2, 'fo')]          # 默认:截断到最短

>>> list(zip(('a', 'b', 'c'), (1, 2, 3), strict=True))
[('a', 1), ('b', 2), ('c', 3)]              # 等长时行为相同

# strict=True 且长度不等时:
# ValueError: zip() argument 2 is longer than argument 1

第三种策略是用 itertools.zip_longest 以常量填充短序列。边界情况:单参数返回 1-元组迭代器,无参返回空迭代器。两个常用技巧:zip(*[iter(s)]*n, strict=True) 把序列切成 n 个一组的块(利用左到右求值顺序);zip(*zip(x, y)) 解包还原两列。zip 是惰性的,元素在被迭代时才处理。

5.3 filter、enumerate、iter

filter(function, iterable) 等价于生成器表达式 (item for item in iterable if function(item))function=None 时按真值过滤,等价于 (item for item in iterable if item)。互补函数是 itertools.filterfalse

enumerate(iterable, start=0) 返回 (计数, 元素) 元组,等价实现是 yield n, elem 的生成器。

iter 有双形态:单参数要求 __iter__ 或从 0 开始的 __getitem__ 序列协议;双参数 iter(callable, sentinel) 每次调用 callable,结果等于 sentinel 时抛 StopIteration——这是构建"块读取器"的经典用法:

from functools import partial
with open('mydata.db', 'rb') as f:
    for block in iter(partial(f.read, 64), b''):
        process_block(block)

5.4 next、anext、reversed、sorted、min/max、sum

  • next(iterator, default):调用 __next__,耗尽时返回 default 或抛 StopIterationanext(3.10)是其异步版,调用 __anext__ 返回 awaitable,耗尽且未给 default 时抛 StopAsyncIteration
  • reversed():要求 __reversed__ 或序列协议(__len__ + __getitem__);
  • sorted(iterable, *, key=None, reverse=False):返回新列表,保证稳定排序(相等元素保持原序,适合多趟排序);仅用 < 比较,建议同时实现全部六个富比较方法;
  • min/max:可作用于可迭代对象或多参数;key 指定单参排序函数,default 处理空可迭代(否则 ValueError);多个极值取最先遇到的那个,与 sorted(...)[0]heapq.nlargest/nsmallest 一致;
  • sum(iterable, /, start=0):从左到右累加,start 不允许为字符串。替代建议:拼接字符串用 ''.join(sequence);浮点高精度求和用 math.fsum;拼接多个可迭代用 itertools.chain。3.12 起浮点求和改用更高精度、更好交换性的算法,3.14 又为复数求和增加了同算法特化。

六、字符串、格式与编码

6.1 chr / ord / ascii / repr / format

  • chr(codepoint) 返回该 Unicode 码点字符,合法范围 0–1,114,111(0x10FFFF),越界抛 ValueErrorord 是其逆:单字符字符串返回码点,长度为 1 的 bytes/bytearray 返回该字节值;
  • ascii(object)repr,但对非 ASCII 字符用 \x/\u/\U 转义,产生类似 Python 2 repr 的输出;
  • repr(object) 尽量返回"可被 eval 还原"的表示,否则返回尖括号包裹的类型名与附加信息;类通过 __repr__ 自定义:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person({self.name!r}, {self.age!r})"
  • format(value, format_spec=""):按 format_spec 格式化,等价于 type(value).__format__(value, format_spec)(绕过实例字典查 __format__);搜索落到 object 且 spec 非空时抛 TypeError。f-string 的 {expr:spec}str.format 最终都走这里。

6.2 round 与浮点陷阱

round(number, ndigits=None):省略 ndigits 时返回最近整数;平局时"四舍六入五成双"(banker's rounding),如 round(0.5)round(-0.5) 均为 0,round(1.5) 为 2。ndigits 可为正、零、负整数;对象委托 __round__。文档特别提醒 round(2.675, 2)2.67 而非 2.68——这是二进制浮点表示的必然结果,不是 bug。

七、open():文件 I/O 的完整参数手册

open 是内置函数中参数最丰富的一个:

open(file, mode='r', buffering=-1, encoding=None, errors=None,
     newline=None, closefd=True, opener=None)

7.1 mode 模式表

字符 含义
'r' 打开读取(默认)
'w' 打开写入,先截断文件
'x' 排他创建,文件已存在则失败(3.3 起,抛 FileExistsError
'a' 打开写入,追加到文件尾(部分 Unix 系统上无论 seek 位置都追加到末尾)
'b' 二进制模式
't' 文本模式(默认)
'+' 读写双向打开

'w+'/'w+b' 截断,'r+'/'r+b' 不截断。二进制/文本的区别由 Python 自身完成(与操作系统文本文件概念无关):二进制返回 bytes 不解码;文本返回 str,先按 encoding 解码。文本模式不指定 encoding 时用 locale.getencoding() 的平台编码。

7.2 buffering:缓冲策略

  • 0:关闭缓冲(仅二进制模式);
  • 1:行缓冲(仅文本写);
  • >1:固定块缓冲(字节数)。

缺省策略:二进制文件按固定块缓冲,大小约为 max(min(blocksize, 8 MiB), DEFAULT_BUFFER_SIZE)(多数系统典型为 128 KiB);交互文本文件(isatty() 为真)行缓冲;其余文本文件同二进制策略。TextIOWrapper 另有独立缓冲,关闭它可用 io.TextIOWrapper.reconfigurewrite_through

7.3 errors、newline、closefd、opener

  • errors:文本模式的编解码错误处理(strictreplaceignore 等,还可用 codecs.register_error 注册的名字);
  • newline(取 None/''/'\n'/'\r'/'\r\n'):读时 None 开启通用换行模式并把 \r\r\n 统一译为 \n'' 开启但不翻译;其余值表示只以该串为行尾。写时 None\n 翻译为 os.linesep''/'\n' 不翻译;
  • closefd:仅当 file 是文件描述符时有效,False 表示关闭 I/O 对象时保留该描述符;给文件名时 closefd 必须为 True
  • opener:自定义打开回调 opener(file, flags) → fd,可用于相对目录打开:
import os
dir_fd = os.open('somedir', os.O_RDONLY)
def opener(path, flags):
    return os.open(path, flags, dir_fd=dir_fd)
with open('spamspam.txt', 'w', opener=opener) as f:
    print('This will be written to somedir/spamspam.txt', file=f)
os.close(dir_fd)  # 不要泄漏文件描述符

7.4 返回类型与行为细节

返回对象类型取决于模式:文本模式返回 io.TextIOWrapper;二进制有缓冲读返回 io.BufferedReader、写/追加返回 io.BufferedWriter、读写返回 io.BufferedRandom;关闭缓冲时返回 io.FileIORawIOBase 子类)。新建文件不可被子进程继承(3.4 起)。3.5 起系统调用被信号中断且处理器未抛异常时会按 PEP 475 重试;3.11 起移除了 'U' 模式。触发审计事件 open

八、属性机制与装饰器:property、classmethod、staticmethod

8.1 property

property(fget=None, fset=None, fdel=None, doc=None)

经典写法定义受控属性 xdoc 缺省时属性文档字符串继承 fget 的 docstring,因此 @property 装饰器能轻松造出只读属性:

class Parrot:
    def __init__(self):
        self._voltage = 100000

    @property
    def voltage(self):
        """Get the current voltage."""
        return self._voltage

getter/setter/deleter 方法可链式构建完整属性(新增函数必须与属性同名):

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

property 对象暴露 fget/fset/fdel 属性;docstring 自 3.5 起可写;3.13 起新增可变的 __name__ 属性。

8.2 classmethod 与 staticmethod

classmethod:类方法以类为隐式首参(@classmethod 声明),可经类或实例调用(实例仅用于取其类);派生类调用时传入的是派生类。3.9 曾允许包装 property 等其他描述符,3.13 已移除该能力。3.10 起继承方法属性(__module____name____qualname____doc____annotations__)并新增 __wrapped__

staticmethod:无隐式首参;3.10 起描述符本身可直接调用,也继承方法属性并有 __wrapped__。在类体内需要避免"自动绑成实例方法"时可写作:

def regular_function():
    ...

class C:
    method = staticmethod(regular_function)

两者都不同于 C++/Java 的静态方法语义——Python 的 classmethod 会随继承传递 cls

九、3.15 新特性:sentinel 哨兵对象

sentinel 是 3.15 新增的内置类,用于创建"唯一标识符"对象:

>>> MISSING = sentinel("MISSING")
>>> MISSING
MISSING

>>> MISSING = sentinel("MISSING", repr="<MISSING>")
>>> MISSING
<MISSING>

语义规则:

  • 哨兵对象为真值(truthy),仅与自身相等,约定用 is 比较;
  • 不支持子类化;浅拷贝/深拷贝都返回对象本身;
  • 支持 | 位或运算符,可出现在类型表达式中——官方推荐的惯用法是"同名变量 + 类型标注":
MISSING = sentinel("MISSING")

def next_value(default: int | MISSING = MISSING):
    ...
  • 属性:__name__(哨兵名)、__module__(创建所在模块名,可写);
  • pickle 支持受限:模块全局作用域下与哨兵名匹配的对象可 pickle 且保身份(pickle.loads(pickle.dumps(PICKLABLE)) is PICKLABLE);类作用域下需名字匹配限定名;函数作用域内定义的不可 pickle。

对比 object()Ellipsis 作哨兵的老套路,sentinel 自带清晰的 repr、类型标注能力和受控的 pickle 行为,是默认参数"未提供"检测的正式方案。

十、其余实用函数速查

  • breakpoint(*args, **kws)(3.7):在调用点进入调试器。它调用 sys.breakpointhook,默认该 hook 调用 pdb.set_trace;用环境变量 PYTHONBREAKPOINT 可切换调试器(如设为 '' 关闭)。触发 builtins.breakpoint 审计事件;
  • divmod(a, b):返回 (商, 余);整数时同 (a // b, a % b);浮点时 q*b + a%b 非常接近 aa%b 非零时与 b 同号且 0 <= abs(a%b) < abs(b)
  • pow(base, exp, mod=None):两参形式同 **;int 负指数得 float(pow(10, -2)0.01);int/float 负底数配非整数指数得复数(pow(-9, 0.5) 接近 3j)。三参模幂比 pow(base, exp) % mod 高效得多;3.8 起支持负指数求模逆:
>>> pow(38, -1, mod=97)
23
>>> 23 * 38 % 97 == 1
True
  • print(*objects, sep=' ', end='\n', file=None, flush=False)sep/end 可为 None(回退默认);file 须有 write(string),缺省用 sys.stdout,不能接二进制流(改用 file.write);flush=True 强制刷新(3.3 新增);
  • help():由 site 模块注入的交互式帮助系统;参数为字符串时按模块/函数/类/关键词/文档主题查找;
  • input(prompt):写提示(不换行)后读一行,返回去尾换行字符串,EOF 抛 EOFError;加载 readline 时获得编辑与历史能力。触发 builtins.inputbuiltins.input/result 两个审计事件;
  • callable(object)(3.2):判断对象是否"看似可调用"(返回 True 不代表调用一定成功,False 则必然失败);类可调用,实例有 __call__ 才可调用;
  • object():一切类的终极基类,构造返回无特征对象且不接受参数;其实例没有 __dict__,不能随意赋属性;
  • super(type, object_or_type=None):沿 MRO 从 type 之后的类开始搜索的代理;零参形式依赖编译器在类方法体内填充。典型单继承用法 super().method(arg)(等价 super(C, self).method(arg))。3.14 起 super 对象可 pickle、可 copy;
  • isinstance/issubclassclassinfo 可传类型的嵌套元组,3.10 起也可传 X | Y 类型联合;非法 classinfo 抛 TypeError(但前面的检查若已成功则不保证抛出)。

十一、__import__:import 语句背后的函数

__import__(name, globals=None, locals=None, fromlist=(), level=0)import 语句调用,文档明确定位为高级函数,日常编程请用 importlib.import_module。替换 builtins.__import__ 可改变 import 语义,但文档强烈反对这种做法(PEP 302 的 import hooks 是更安全的替代)。关键行为:

  • import spam 编译为类似 spam = __import__('spam', globals(), locals(), [], 0)
  • import spam.ham 绑定的是顶层包spam = __import__('spam.ham', globals(), locals(), [], 0)
  • from spam.ham import eggs, sausage as saus 因 fromlist 非空而返回 spam.ham 模块本体,再从其中取属性;
  • level=0 只绝对导入;正数表示相对导入的父包层数(PEP 328);3.3 起不支持负数。

十二、源码定位:内置函数在 CPython 中如何实现

结合当前仓库源码,内置函数相关的关键落点:

  • Python/bltinmodule.cbuiltins 模块主体,注册各内置函数入口;参数解析代码由 Tools 中的 clinic 工具生成到 Python/clinic/bltinmodule.c.h
  • Objects/dictobject.c:3.15 的 frozendict 在此与 dict 共用核心实现,frozendict_new(约 L139)构造不可变实例,写/删路径经 frozendict_does_not_support 宏统一拒绝(约 L2800);
  • Include/internal/pycore_dict.h:内部声明 PyFrozenDict_Type,供解释器其他子系统(如 eval/exec 的 globals 校验)识别 frozendict;
  • 审计事件(compileexecopenbuiltins.idbuiltins.input 等)由 Include/audit.h 定义的 PySys_Audit 机制驱动,可被 sys.addaudithook 钩住,是安全加固(沙箱、行为监控)的官方抓手。

结语

Doc/library/functions.rst 所定义的这套内置函数,覆盖了 Python 的类型构造、动态执行、反射自省、迭代处理和文件 I/O 五大核心能力。使用时的三条主线建议:其一,动态执行(eval/exec)永远不要接受不可信输入,__builtins__ 覆写不是安全边界;其二,并行可迭代场景优先加 strict=Truezipmap),把"长度不一致"的静默截断变成显式 ValueError;其三,默认参数"未提供"检测从 3.15 起有了 sentinel 这一官方标准件。再配合源码中的 Python/bltinmodule.cObjects/dictobject.c,本文所述的每个行为都能在 CPython 实现中找到对应落点,便于进一步深入。

登录后查看全文
热门项目推荐
相关项目推荐