File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -48,6 +48,8 @@ Py_INCREF(value);
4848PUSH(value); // 压入求值栈
4949```
5050
51+ 
52+
5153这是 Python 里取值最快的路径——一次数组索引而已。这也解释了一个常见报错的由来:如果这个槽位还没被赋值就被读取,`GETLOCAL` 取到 `NULL`,于是抛 **`UnboundLocalError`**:
5254
5355```python
@@ -119,6 +121,8 @@ if (v == NULL) {
119121}
120122```
121123
124+ ![ LOAD_NAME 运行期依次查三个名字空间] ( name-lookup.svg )
125+
122126可以看到 ` LOAD_NAME ` 比 ` LOAD_GLOBAL ` 多查一层局部、比 ` LOAD_FAST ` 多了字典查找——它最灵活,但也最慢。这正是为什么** 函数内部要尽量用局部变量** :函数体里的名字能走 ` LOAD_FAST ` 的快路径,而模块顶层只能用 ` LOAD_NAME ` 。
123127
124128## LEGB:四类作用域与四条指令
@@ -181,6 +185,8 @@ while (--oparg >= 0) {
181185PUSH (list); // 列表压回栈顶
182186```
183187
188+ ![ BUILD_LIST 把栈顶值打包成列表] ( build-list.svg )
189+
184190` BUILD_TUPLE ` 、` BUILD_MAP ` (字典)、` COMPARE_OP ` (比较)……全是这个模式:操作数已经在栈上备好,指令弹出它们、算出结果、压回栈顶。理解了「** 压操作数 → 指令计算 → 压回结果** 」这一条,绝大多数表达式字节码都能照着读下来。
185191
186192---
You can’t perform that action at this time.
0 commit comments