news 2026/4/21 17:32:13

Python 3.12 Special Attribute - 26 - __builtins__

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 3.12 Special Attribute - 26 - __builtins__

Python 3.12 Special Attribute -__builtins__


__builtins__是 Python 中一个特殊的内置属性,它存在于每个模块的全局命名空间中(通常作为模块的属性)。它提供了对 Python内置命名空间(builtins)的访问,包含了所有内置函数(如printlen)、内置异常(如Exception)、内置常量(如TrueFalse)等。理解__builtins__有助于深入掌握 Python 的作用域机制、动态修改内置行为(尽管不推荐),以及实现自定义执行环境。


1.__builtins__的基本概念

  • 定义__builtins__是一个模块(通常)或字典,它引用 Python 的内置命名空间。通过它可以访问所有内置名称。
  • 类型:在大多数情况下(例如在主模块中),__builtins__是一个模块对象(builtins模块);在某些上下文(如execeval的受限环境)中,它可能是一个字典。
  • 位置:每个模块(包括__main__)的全局命名空间中都有__builtins__属性。它通常由解释器在模块初始化时自动设置。
  • 可写性__builtins__是可写的,但直接修改它可能导致不可预知的行为(例如破坏内置函数的可用性)。通常不应修改。

示例

importbuiltinsprint(__builtins__isbuiltins)# True(在大多数情况下)print(__builtins__.printisprint)# True

2.__builtins__builtins模块的关系

Python 标准库中有一个名为builtins的模块,它直接暴露所有内置名称。__builtins__通常就是这个模块的引用。但需要注意,在某些执行环境(如execeval中指定了自定义的全局命名空间)中,__builtins__可能被设置为一个字典(即{'print': print, ...}),而不是完整的builtins模块。

验证

importbuiltinsprint(__builtins__isbuiltins)# 输出 True(在普通 Python 脚本中)

3. 不同模块中的__builtins__行为

  • 主模块(__main____builtins__指向builtins模块。
  • 被导入的模块:解释器在导入模块时,会自动为该模块的全局命名空间设置__builtins__属性,同样指向builtins模块(除非被覆盖)。
  • execeval的受限环境:如果调用exec(code, globals)时没有提供内置字典,Python 会自动将__builtins__设置为当前内置模块的字典(或模块)。但如果提供了自定义globals且未包含__builtins__,Python 会自动注入一个字典形式的__builtins__

4. 用途与典型场景

  • 动态访问内置函数:通过__builtins__可以在运行时获取内置函数的引用,例如getattr(__builtins__, 'len')
  • 限制或替换内置函数:在沙盒环境中,可以通过替换__builtins__中的条目来禁用危险函数(如openeval),但这种方法不是绝对安全的(因为存在多种绕过方式)。
  • 自省:列出所有内置名称(例如dir(__builtins__))。
  • 实现自定义执行环境:在execeval中,通过提供自定义的__builtins__字典来控制可用函数。

5. 示例与逐行解析

示例 1:查看__builtins__的内容

# 打印所有内置名称print(dir(__builtins__))# 获取特定内置函数print(__builtins__.len([1,2,3]))# 3

逐行解析

代码解释
2dir(__builtins__)列出__builtins__中所有名称,包括lenprintException等。
5__builtins__.len([1,2,3])通过__builtins__调用内置函数len

为什么这样写?

  • 演示了__builtins__提供了访问所有内置名称的途径。

示例 2:检查__builtins__的类型

print(type(__builtins__))# <class 'module'> (在普通脚本中)print(__builtins__is__builtins__.__dict__)# False(因为 __builtins__ 是模块,不是字典)

注意:在exec环境中,__builtins__可能是一个字典。可以通过isinstance(__builtins__, dict)判断。

示例 3:动态调用内置函数(通过名称字符串)

func_name='max'ifhasattr(__builtins__,func_name):func=getattr(__builtins__,func_name)print(func([1,5,3]))# 5

逐行解析

代码解释
1func_name = 'max'内置函数名的字符串。
2hasattr(__builtins__, func_name)检查__builtins__是否有该名称。
3func = getattr(__builtins__, func_name)获取函数对象。
4func([1,5,3])调用内置函数max

为什么这样写?

  • 这种方式允许在运行时根据字符串动态调用内置函数,适用于配置驱动或元编程。

示例 4:临时替换内置函数(危险操作,仅作演示)

original_print=__builtins__.printdefmy_print(*args,**kwargs):original_print("Custom print:",*args)# ✅ 使用保存的原始函数__builtins__.print=my_printprint("Hello")# 输出: Custom print: Hello# 恢复__builtins__.print=original_printprint("Hello")# 输出: Hello

逐行解析

代码解释
1保存原始print函数以便后续恢复。
3-5定义自定义print添加前缀。
7替换__builtins__.print所有后续print调用都会使用新函数。
9调用print输出自定义内容。
11-12恢复原始print还原内置行为。

为什么这样写?

  • 演示了如何修改内置行为,但强烈不建议在生产环境中使用,因为这会影响整个进程,且可能导致难以调试的 bug。通常只在测试或特殊框架中临时使用。

示例 5:在exec中使用自定义__builtins__

custom_builtins={'print':lambdax:print(f"Custom:{x}"),'len':len,}code=""" print("Hello") print(len([1,2,3])) """exec(code,{'__builtins__':custom_builtins})

输出

Custom: Hello 3

逐行解析

代码解释
1-4定义自定义内置字典只提供printlen,其中print被修改。
6-9待执行的代码使用了printlen
11exec执行将自定义的__builtins__作为全局字典的一部分传入。

为什么这样写?

  • 创建受限的执行环境,只允许使用特定的内置函数。常用于代码沙盒或模板引擎中。

6. 底层实现机制(CPython)

在 CPython 中,__builtins__的设置发生在模块初始化和执行代码块时。

  • 主模块(__main__:当 Python 启动时,会创建一个主模块对象,并将其全局字典中的__builtins__设置为builtins模块(即PyEval_GetBuiltins()返回的模块)。
  • 导入的模块:在import语句加载模块时,importlib会创建新的模块对象,并自动将其__builtins__属性设置为builtins模块。这发生在_bootstrap._load_unlocked中。
  • execeval:当执行动态代码时,Python 会根据提供的全局字典决定__builtins__的值:
    • 如果全局字典中已有__builtins__键,则使用其值。
    • 否则,如果全局字典中包含了'__builtins__'且值为None,则内置名称将不可用。
    • 否则,Python 会自动注入一个__builtins__条目:如果全局字典的__name__'__main__',则设置为builtins模块;否则设置为builtins.__dict__(字典形式)。

内置模块 vs 字典

  • 在模块顶层,__builtins__通常是一个模块对象,因为直接使用模块可以保持完整的命名空间,且效率更高。
  • 在动态代码(exec)中,使用字典更轻量,且方便进行受限控制。

安全性:尽管可以通过替换__builtins__来限制内置函数,但仍存在绕过方式(例如通过().__class__.__bases__[0].__subclasses__()等技巧访问危险函数)。因此,依赖__builtins__的沙盒并不安全。


7. 注意事项与陷阱

  • 不要随意修改__builtins__:修改全局内置函数会影响整个 Python 进程,可能导致其他模块产生意外行为。
  • __builtins__可能不是模块:在exec或某些特定上下文中,它可能是一个字典。因此,不要假设它有__dict__属性或可以直接导入。
  • builtins模块是更好的选择:如果需要显式访问内置名称,推荐直接导入builtins模块,因为它更明确、更可靠。
    importbuiltinsprint(builtins.printisprint)# True
  • __builtin__(Python 2)的区别:在 Python 3 中,__builtins__代替了 Python 2 的__builtin__模块。
  • 避免在库代码中依赖__builtins__:因为库可能被导入到自定义环境中,其中__builtins__可能被修改。

8. 与其他特殊属性的关系

属性关系
__name__模块名。__builtins__是模块的属性,独立于__name__
__dict__模块的命名空间字典。__builtins__是该字典中的一个键。
__file__模块的文件路径,与__builtins__无关。
builtins标准库模块,通常与__builtins__指向同一个对象。

9. 总结

特性说明
角色提供对 Python 内置命名空间的访问
类型通常是builtins模块(对象),也可能是字典
位置每个模块的全局命名空间
访问方式__builtins__.function_name或直接导入builtins
可写性可写,但强烈不建议修改
底层由解释器在模块初始化时自动设置
典型用途动态访问内置函数、受限执行环境、自省
最佳实践直接使用import builtins;不要依赖__builtins__进行安全控制

掌握__builtins__有助于深入理解 Python 的作用域和内置命名空间的管理。虽然日常开发中很少直接操作它,但在编写框架、调试或实现动态执行环境时,它是一个有用的工具。希望本文能帮助你全面掌握这一特殊属性。

如果在学习过程中遇到问题,欢迎在评论区留言讨论!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 7:36:30

Android 单 Activity 架构下的 Splash Screen 与主题规范指南

在传统的 Android 多 Activity 架构中&#xff0c;开发者通常会创建一个独立的 SplashActivity 来展示品牌 Logo 或启动动画&#xff0c;然后再跳转到 MainActivity 并将自身 finish() 掉。 然而&#xff0c;在单 Activity 架构&#xff08;尤其是结合 Jetpack Compose Navigat…

作者头像 李华
网站建设 2026/4/20 5:43:30

小白也能懂!用Ollama部署LFM2.5-1.2B-Thinking,体验边想边说的AI对话

小白也能懂&#xff01;用Ollama部署LFM2.5-1.2B-Thinking&#xff0c;体验边想边说的AI对话 1. 为什么选择LFM2.5-1.2B-Thinking 你有没有想过在自己的电脑上运行一个真正智能的对话AI&#xff1f;不是那种需要高端显卡、占用大量内存的"大块头"&#xff0c;而是一…

作者头像 李华
网站建设 2026/4/20 5:37:28

PyTorch 2.8深度学习镜像基础教程:使用git submodule管理模型依赖

PyTorch 2.8深度学习镜像基础教程&#xff1a;使用git submodule管理模型依赖 1. 镜像环境介绍 PyTorch 2.8深度学习镜像是一个专为RTX 4090D 24GB显卡优化的高性能计算环境&#xff0c;基于CUDA 12.4和驱动550.90.07深度调优。这个镜像预装了完整的深度学习工具链&#xff0…

作者头像 李华
网站建设 2026/4/21 7:35:58

YOLO X Layout文档版面分析:从安装到API调用,新手一站式指南

YOLO X Layout文档版面分析&#xff1a;从安装到API调用&#xff0c;新手一站式指南 1. 为什么需要文档版面分析&#xff1f; 在日常工作和学习中&#xff0c;我们经常遇到这样的场景&#xff1a;收到一份扫描的PDF合同&#xff0c;需要提取关键条款&#xff1b;或者拿到一份…

作者头像 李华
网站建设 2026/4/21 5:40:02

RWKV7-1.5B-g1a实操手册:如何用systemd替代supervisorctl实现服务管理

RWKV7-1.5B-g1a实操手册&#xff1a;如何用systemd替代supervisorctl实现服务管理 1. 平台简介 rwkv7-1.5B-g1a是基于RWKV-7架构的多语言文本生成模型&#xff0c;特别适合基础问答、文案续写、简短总结和轻量中文对话场景。相比传统管理工具supervisorctl&#xff0c;使用sys…

作者头像 李华