网易首页 > 网易号 > 正文 申请入驻

Python:代码对象

0
分享至

在 Python 的执行模型中,可执行代码并不是以字符串或抽象语法树的形式直接运行。源码在执行之前,会被编译为一种中间表示——代码对象(code object)。代码对象是 Python 对“可执行逻辑结构”的静态描述,是连接源码与运行期执行机制的关键枢纽。

在对象模型层面,代码对象并不负责执行,也不承载状态,而是作为一种描述对象,为后续的执行对象(函数对象、帧对象)提供结构蓝本。理解这一点,是正确理解函数、闭包、作用域以及调用机制的前提。

一、什么是代码对象

从概念上看,代码对象(code object)是对一段可执行 Python 代码结构的抽象描述。

代码对象并不保存源码文本,也不保存抽象语法树,而是描述:

• 这段代码将被编译成哪些字节码指令

• 执行时需要怎样的局部变量与参数布局

• 会使用到哪些字面量及编译阶段嵌入的字面量值对象

• 词法作用域关系如何建立

• 控制流(跳转、异常处理)应如何进行

代码对象不是:

• 函数对象(代码对象不可调用)

• 方法对象(代码对象不参与绑定)

• 帧对象(代码对象不保存局部变量、不维护指令指针)

这一定位决定了代码对象在整体模型中的角色:

代码对象负责描述执行结构,而不负责执行行为。

正是基于这一点,Python 在对象模型中明确区分了“描述对象”与“执行对象”,从而避免了结构描述与运行状态的混杂。

二、代码对象的产生:从源码到执行单元

当 Python 解释器处理一段源码时,会经历以下阶段:

1、解析(Parsing):源码 → 抽象语法树(AST)

2、编译(Compilation):AST → 代码对象

3、执行(Execution):执行对象引用代码对象 → 创建帧对象 → 解释执行字节码

以函数定义为例:

    

在函数定义语句被执行时:

1、函数体会先被编译为一个代码对象

2、随后解释器创建函数对象

3、函数对象持有该代码对象(通过 __code__ 属性)

更准确地说,在函数定义语句被执行的过程中,函数体对应的代码对象先被构造,随后才创建函数对象;函数对象只是对代码对象的一种执行语义封装。这一顺序在理解闭包、装饰器和函数动态构造时尤为重要。

需要说明的是,代码对象并不仅存在于函数中。事实上,在 Python 中凡是“可独立执行的代码块”,其编译结果都是代码对象。

例如:

• 模块顶层代码

• 类体

• 列表推导式、生成器表达式

• lambda 表达式

# True

这说明代码对象是 Python 执行模型中对可执行结构的基础抽象,而非函数的附属品。

三、对象协作:描述对象与执行对象的分层设计

在 Python 中,一次函数调用至少涉及三类对象:

• 代码对象:描述“执行结构”,被函数对象持有

• 函数对象:提供“可调用语义”,触发创建

• 帧对象:承载“运行期状态”,引用代码对象执行

这种分层并非实现巧合,而是对象模型层面的刻意设计。

1、为什么要区分“描述对象”与“执行对象”

如果将执行逻辑与运行状态混合在同一对象中,将直接导致以下问题:

• 同一段代码无法被多次、安全地复用

• 递归调用无法独立维护状态

• 闭包变量无法被可靠捕获

通过将代码对象设计为纯描述对象,Python 实现了:

• 一段代码 → 多次执行

• 一份结构 → 多个帧实例

• 一次定义 → 多种调用路径

从模型上可以概括为:

代码对象是“静态蓝本”,帧对象是“动态实例”。

下面通过递归与多次调用两个典型场景,具体说明这一分层为何不可或缺。

递归示例:

    

在该示例中:

• fact 对应的代码对象只有一个

• 每一次递归调用都会创建一个新的帧对象

• 各帧对象分别保存各自的 n 值与执行位置

如果代码对象本身保存执行状态,递归调用将无法区分不同层级的执行上下文。

多次调用示例:

inc(10)  # 11

这里同样是:

• 同一个代码对象被反复使用

• 每次调用生成独立的帧对象

• 调用之间不存在状态干扰

这说明,只有将“执行结构”与“执行状态”严格分离,代码的可重入性与可组合性才能成立。

2、代码对象与函数对象的关系

函数对象的职责,并不是保存代码结构,而是:

• 关联代码对象(__code__)

• 绑定全局命名空间(__globals__)

• 绑定默认参数

• 绑定闭包变量(如有)

type(f.__code__)    #

同一个代码对象,理论上可以被多个函数对象共享,这也正是 types.FunctionType 能够存在的基础。

四、代码对象如何描述执行结构

代码对象内部包含大量只读字段,用于完整描述一段代码的执行形态。以下仅讨论与语义最直接相关的部分。

1、co_consts

co_consts 并非语言意义上的“常量表”,而是编译阶段嵌入字节码中的字面量值及嵌套代码对象的集合。

f.__code__.co_consts  # (None, 1)

其中 None 对应编译器为函数体插入的隐式返回值字面量。

2、co_argcount 与 co_varnames

这两者共同描述参数与局部变量的布局方式。

• co_argcount:位置参数的数量

• co_varnames:局部变量名(包含参数)的元组

它们决定了帧对象中局部命名空间的槽位结构。

3、co_names

co_names 记录运行期需要通过名称解析的标识符,用于驱动全局查找与属性访问,例如:

• 全局变量名

• 内置函数名

• 属性名

解释器在执行相关字节码时,会通过该表进行名称解析。

4、co_cellvars 与 co_freevars

这两个字段用于支持闭包与词法作用域。

• co_cellvars:在本层定义、但被内层函数引用的变量

• co_freevars:来自外层作用域、被当前代码使用的自由变量

它们共同定义了变量如何被捕获并在多层函数调用中保持一致性。

五、执行关系:从代码对象到闭包与作用域

1、代码对象视角下的闭包形成机制

考虑如下示例:

    

在编译阶段:

• outer 的代码对象将 x 标记为 co_cellvars

• inner 的代码对象将 x 标记为 co_freevars

这一步完全发生在代码对象层面,尚未涉及任何运行时值。

在执行阶段:

• 调用 outer 时创建帧对象

• x 被放入 cell 对象中

• inner 函数对象持有对该 cell 的引用

由此可见,代码对象只负责声明“哪些变量需要被闭包捕获”,而不负责捕获行为本身。

捕获发生在函数对象与帧对象的协作中,而不是在代码对象中。

2、作用域为何必须在代码对象阶段确定

作用域关系一旦进入执行期再动态决定,将导致:

• 解释器执行复杂度激增

• 闭包语义不稳定

• 名称解析行为不可预测

因此 Python 选择:

• 在编译期由代码对象静态声明作用域结构

• 在运行期由帧对象动态承载具体值

这是“描述对象 vs 执行对象”分层设计在闭包机制中的直接体现。

小结

代码对象在 Python 对象模型中承担的是“执行结构描述者”的角色,而非执行者本身。它在编译阶段确定代码的指令结构、变量布局与作用域关系,在运行期由函数对象与帧对象协同完成实际执行。

通过将代码对象设计为不可变的描述对象,并与执行对象严格分层,Python 实现了闭包、递归与高阶函数等机制的高度一致性与可组合性。理解代码对象,是理解 Python 执行语义与对象模型统一性的关键一环。


点赞有美意,赞赏是鼓励

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

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.

相关推荐
热点推荐
杨紫,值得一个肯定!

杨紫,值得一个肯定!

星寒新影视
2026-02-03 21:40:40
20年前,张冕为护胡歌离世,胡歌许诺赡养其父母,如今他做到了吗

20年前,张冕为护胡歌离世,胡歌许诺赡养其父母,如今他做到了吗

科学发掘
2026-02-04 02:44:46
医院直播给女性患者做手术,隐私部位被全程直播!观看人数超5万

医院直播给女性患者做手术,隐私部位被全程直播!观看人数超5万

火山诗话
2026-02-03 18:44:11
官方:吉达联合与34岁法国中场坎特解约

官方:吉达联合与34岁法国中场坎特解约

懂球帝
2026-02-04 05:51:28
爱泼斯坦的“萝莉岛”和赖昌星的“红楼”及许家印的“白宫”

爱泼斯坦的“萝莉岛”和赖昌星的“红楼”及许家印的“白宫”

壹家言
2026-02-04 00:34:08
赵露思已经把人香晕了 柔光潋滟

赵露思已经把人香晕了 柔光潋滟

只要高兴就好
2025-12-29 08:02:22
妻子把58万奖金全转给了小叔子,我平静说:公司派我去外地工作6年。三天后她打了61通电话,发了145条语音,我直接静音

妻子把58万奖金全转给了小叔子,我平静说:公司派我去外地工作6年。三天后她打了61通电话,发了145条语音,我直接静音

奶茶麦子
2026-02-03 16:17:07
委内瑞拉人肠子悔青,如果这位总统还在,他们的国家何至于此?

委内瑞拉人肠子悔青,如果这位总统还在,他们的国家何至于此?

千秋文化
2026-01-09 14:26:11
美印达成协议:几千年封闭印度开始完全开放,美经贸重构完成闭环

美印达成协议:几千年封闭印度开始完全开放,美经贸重构完成闭环

邵旭峰域
2026-02-03 12:40:32
美国梦塌房?大批华裔二代反水,痛骂父母移民美国错过中国崛起红利

美国梦塌房?大批华裔二代反水,痛骂父母移民美国错过中国崛起红利

青梅侃史啊
2026-02-02 22:04:03
浙江省委书记,看望96岁抗战老兵

浙江省委书记,看望96岁抗战老兵

上观新闻
2026-02-04 06:29:05
美国司法部误公开爱泼斯坦案“数十张未打码裸照”!新采访披露其自称“一级X掠食者”

美国司法部误公开爱泼斯坦案“数十张未打码裸照”!新采访披露其自称“一级X掠食者”

纽约时间
2026-02-03 05:55:45
萝莉岛吃人真相

萝莉岛吃人真相

哲空空
2026-02-03 16:42:15
诬陷逃单后续:老板娘哭另有隐情,拉员工顶包道歉,店铺生意黄了

诬陷逃单后续:老板娘哭另有隐情,拉员工顶包道歉,店铺生意黄了

奇思妙想草叶君
2026-02-04 02:26:02
补偿N+4! 德国巨头博世在华启动人员优化,燃油汽车项目成“重灾区”

补偿N+4! 德国巨头博世在华启动人员优化,燃油汽车项目成“重灾区”

新浪财经
2026-02-03 08:19:50
韩媒:中国欠特朗普一声谢谢!要不是美国打压,中国芯不会那么强

韩媒:中国欠特朗普一声谢谢!要不是美国打压,中国芯不会那么强

互联网.乱侃秀
2026-02-03 10:27:19
没有卖惨,承认自己过气,百万网红自曝月收入5千,对收入挺满意

没有卖惨,承认自己过气,百万网红自曝月收入5千,对收入挺满意

阿废冷眼观察所
2026-02-04 02:26:04
郭士强有魄力!中国男篮官宣21人名单:赵睿胡金秋领衔,周琦落选

郭士强有魄力!中国男篮官宣21人名单:赵睿胡金秋领衔,周琦落选

大秦壁虎白话体育
2026-02-03 23:21:43
1-3到5-3!吴宜泽开门红,张安达爆冷世界冠军,丁俊晖破百救赛点

1-3到5-3!吴宜泽开门红,张安达爆冷世界冠军,丁俊晖破百救赛点

刘姚尧的文字城堡
2026-02-03 22:30:13
12306回应“每天都用前任的身份证订票不付款取消3次让他买不了过年回家的票”:锁的是订票账户

12306回应“每天都用前任的身份证订票不付款取消3次让他买不了过年回家的票”:锁的是订票账户

新浪财经
2026-02-02 23:00:39
2026-02-04 10:08:49
MediaTea
MediaTea
专业的数字媒体、新媒体技术
1736文章数 72关注度
往期回顾 全部

科技要闻

李飞飞:AI的终点不是写代码,而是人类的尊严

头条要闻

强奸大嫂凶手出狱后去大嫂家 大嫂吓得穿内衣跑出求救

头条要闻

强奸大嫂凶手出狱后去大嫂家 大嫂吓得穿内衣跑出求救

体育要闻

“也许我的一小步,会成为中国足球的一大步”

娱乐要闻

大S逝世一周年 S家没通知大S子女惹争议

财经要闻

中央一号文件:扎实推进乡村全面振兴

汽车要闻

上汽决定不再等那个“正确答案”了

态度原创

旅游
本地
艺术
公开课
军事航空

旅游要闻

建昌:辽西秘境中,一部活态的山水人文史诗

本地新闻

云游中国|拨开云雾,巫山每帧都是航拍大片

艺术要闻

挑战你的认字能力!只需14字,教你轻松恢复写字!

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

特朗普:庞大兵力将很快抵达伊朗

无障碍浏览 进入关怀版