builtins 是 Python 标准库中用于访问内置对象的模块,包含常用函数、类型、异常类及部分常量。日常使用的 print()、len()、list 和 ValueError 等,都可以通过这个模块显式访问。
理解 builtins,有助于掌握内置名称的查找方式、排查同名变量引起的错误,并在封装内置功能时保留原有行为。
一、导入与常见应用场景
1、导入模块
builtins 随 Python 提供,无需额外安装。
通常可以直接使用 len()、print() 等内置函数,不需要先导入 builtins。显式导入主要用于明确对象来源或处理名称冲突。
2、常见应用场景
• 查看内置对象:了解当前环境提供的函数、类型和异常类。
• 排查名称冲突:检查 list、sum、open 等名称是否被重新绑定。
• 封装内置功能:在增加输出前缀、默认编码等行为时调用原有功能。
• 理解名称查找:区分局部名称、模块全局名称与内置名称。
• 辅助测试:理解临时替换内置函数时的影响范围。
3、与相关模块的分工
• builtins:显式访问内置对象。
• sys:获取解释器信息、标准流和运行状态。
• inspect:检查函数签名、源码和对象结构。
• keyword:判断字符串是否为关键字或软关键字。
• unittest.mock:在测试中临时替换对象并恢复。
二、内置对象与名称查找
1、内置命名空间
命名空间(Namespace)组织名称与对象之间的绑定关系。内置命名空间保存解释器为程序提供的一组基础名称。
在通常的运行环境中,下面两种写法访问同一个对象:
以上结果以相关名称未被重新绑定为前提。
2、内置对象的主要类别
• 内置函数:例如 len()、print()、abs()、sum() 和 open()。
• 内置类型:例如 int、float、str、list、tuple、dict 和 set。
• 内置异常类:例如 ValueError、TypeError、KeyError 和 OSError。
• 内置常量:例如 None、True、False、Ellipsis 和 NotImplemented。
int()、list() 等虽然采用调用形式,但 int 和 list 本身是类型对象;调用它们通常用于创建或转换对象。
3、名称查找顺序
普通函数中的名称查找通常可按 LEGB 理解:
• Local:当前函数的局部作用域。
• Enclosing:外层函数的作用域。
• Global:当前模块的全局作用域。
• Built-in:内置作用域。
这一概括适合普通函数场景;类体、注解作用域等存在专门规则,不宜将其机械套用于所有代码结构。
输出:
3局部变量 len 遮蔽了同名内置函数,但没有修改 builtins.len。
4、内置名称与关键字
内置名称通常允许重新绑定,例如 list、sum 和 open。关键字(Keyword)受语法规则约束,例如 if、for 和 return。
True、False 和 None 同时具有关键字地位,不能像普通变量一样重新赋值。
三、查看与访问内置对象
1、查看可用名称
dir() 适合交互式查看名称。以上筛选只是隐藏以下划线开头的项目,不代表这些项目不可用。
内置名称集合可能受到解释器和启动环境影响,不宜依赖固定数量。
2、通过属性显式访问
普通业务代码通常直接使用 len()、sum() 和 sorted()。只有需要明确来源时,再采用 builtins.名称 的形式。
3、按字符串获取对象
getattr() 按属性名取值;属性不存在且没有提供默认值时,会抛出 AttributeError。
如果名称来自外部输入,宜建立明确的允许列表,不应直接开放任意内置对象的调用。
4、查看说明与名称字典
vars(builtins) 返回模块实际使用的属性字典,并非副本。修改其中的项目会改变模块属性,因此这里只用于读取。
help() 通常由启动时加载的 site 模块提供;特殊启动环境中可能不可用。
四、名称遮蔽与冲突处理
1、常见的名称遮蔽
名称遮蔽(Name Shadowing)是指较近作用域中的同名绑定,使原有名称无法通过普通查找直接访问。
这里的 del list 删除当前模块中的名称绑定。在没有其他同名绑定的通常环境下,后续使用 list 会重新找到内置类型。
实际开发中,应优先将变量改为 items、records、values 等具有明确含义的名称。
2、函数局部名称的影响
函数体内存在对某个名称的赋值时,除非使用 global 或 nonlocal 声明,该名称通常会被认定为局部名称。
虽然赋值写在后面,前面的 len 仍被视为尚未赋值的局部变量,不会继续查找内置函数。
同样,在函数中删除局部同名变量,也不会使该局部名称自动恢复为内置名称。此类问题通常应通过重命名解决。
3、局部重绑定与模块属性修改
下面两种操作影响不同:
修改 builtins.len 可能影响同一解释器内其他使用该内置名称的代码。普通应用不宜通过这种方式改变基础行为。
builtins 提供显式访问入口,但不是不可修改的“原始对象备份”。如果属性本身已被替换,通过 builtins 访问到的也会是替换后的对象。
五、常用内置功能示例
1、类型转换与类型判断
转换失败会产生相应异常,例如 int("85分") 会抛出 ValueError。
isinstance() 会考虑继承关系。bool 是 int 的子类,因此 isinstance(True, int) 为 True;若业务上需要排除布尔值,应单独处理。
2、聚合与排序
sorted() 返回新列表,不会原地修改输入列表。min() 和 max() 处理空可迭代对象时,可通过 default 指定返回值:
print(max([], default=None)) # None3、编号与并行遍历
输出:
2 李四 85zip() 默认在最短输入耗尽时结束;strict=True 会在迭代过程中发现长度不一致时抛出 ValueError,适合要求逐项对应的数据。
4、迭代与真值判断
next() 在迭代器耗尽时返回指定默认值;未提供默认值时,会抛出 StopIteration。
all() 和 any() 根据元素的真值判断,并在结果确定后停止读取。对迭代器使用时,已经读取的元素会被消耗。
六、封装内置功能
1、为输出添加前缀
通常使用新的函数名封装内置功能即可:
输出:
[信息] 处理完成 共 3 条记录kwargs 可以继续传递 sep、end、file 和 flush 等打印参数。
2、同名函数中的内置调用
确有同名接口需求时,可通过 builtins 避免函数调用自身:
本例是面向文本文件的简化封装,并非完整替代内置 open()。再次运行会覆盖 message.txt。
内置 open() 的二进制模式不接受 encoding 参数。若只需统一文本编码,实际项目中使用 open_text() 之类的名称通常更清楚。
七、动态执行与内置命名空间
1、eval() 与 exec()
eval() 用于求值表达式,exec() 用于执行语句序列:
这些操作会实际执行代码。读取数字或结构化数据时,应优先使用 int()、float()、json.loads() 等与输入格式相匹配的工具。
2、__builtins__ 与 builtins
builtins 是可显式导入的模块;__builtins__ 则是执行环境中可能出现的实现细节,其值可能是模块,也可能是模块字典。
普通代码应使用 import builtins 访问内置对象,不宜依赖 __builtins__ 的具体形态。
当向 eval() 或 exec() 提供的全局字典中没有 __builtins__ 项时,解释器会插入内置模块的字典。因此,传入空字典并不表示禁用了内置功能。
print("__builtins__" in namespace) # True3、动态执行的使用边界
限制 __builtins__ 中的名称不能构成可靠的安全隔离。不要将不可信输入直接交给 eval() 或 exec() 执行。
如果只是根据操作名称选择功能,可使用允许列表,将名称映射到明确的函数。
八、应用举例:按名称选择统计操作
以下示例将允许使用的内置函数保存在字典中,按指定名称完成统计:
输出:
sorted: [75, 88, 90]示例统一拒绝空数据,这是应用层规则,并非这些函数都不能处理空输入。
转换为列表便于检查和重复使用数据,但会消耗输入迭代器并占用相应内存。示例面向可装入内存的有限数值数据,不适合无限迭代器。
允许列表明确了可调用范围,也避免使用 eval() 解析操作名称。
九、常用函数与访问形式速览
以下列出常用调用形式,省略部分可选参数。
• builtins.名称:显式访问指定内置对象。
• dir(builtins):查看模块中的名称。
• vars(builtins):获取模块实际使用的属性字典。
• getattr(builtins, name):按字符串名称获取对象。
• hasattr(builtins, name):检查指定属性是否存在。
• len(obj):返回对象的元素数量或长度。
• isinstance(obj, classinfo):检查对象是否属于指定类型或其子类。
• sorted(iterable, key=None, reverse=False):返回排序后的新列表;key 和 reverse 以关键字方式传入。
• enumerate(iterable, start=0):迭代产生编号与元素。
• zip(*iterables, strict=False):并行迭代多个输入。
• iter(iterable):获取迭代器。
• next(iterator, default):获取下一项,耗尽时返回默认值。
• all(iterable)、any(iterable):判断元素的真值情况。
• callable(obj):判断对象是否可调用,但不保证某次具体调用一定成功。
十、补充说明
1、保持内置名称清晰
避免将 list、dict、str、sum、max、input 等名称用于无关变量。名称冲突通常应从命名处修正,无需在所有调用前添加 builtins.。
2、区分类型与对象方法
len(values) 是内置函数调用,values.append(item) 是对象方法调用。builtins 不会将所有类型的方法都作为模块顶层函数提供。
3、避免直接修改内置模块
直接替换 builtins.print 或 builtins.open 可能影响其他模块。测试确需临时替换时,宜使用 unittest.mock.patch() 等能够恢复对象的工具,并在被测代码实际查找该名称的位置进行替换。
4、内置对象与启动环境
help、quit 和 exit 等名称通常由 site 模块加入。quit() 和 exit() 主要用于交互环境;脚本需要控制退出状态时,通常使用 sys.exit()。
5、异常类的显式访问
ValueError、TypeError 等通常直接使用即可。需要明确来源时,也可以写成 builtins.ValueError、builtins.TypeError,但没有必要普遍增加此前缀。
小结
builtins 提供内置函数、类型和异常类的显式访问入口。理解名称查找与遮蔽,有助于排查冲突、封装功能并保持接口清晰。普通代码优先直接使用内置名称,确有需要时再通过 builtins 明确访问。
![]()
“点赞有美意,赞赏是鼓励”
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.