show | version | enable_checker |
---|---|---|
step |
1.0 |
true |
- 我们把python源文件
- 词法分析 得到 词流(token stream)
- 语法分析 得到 抽象语法树(Abstract Syntax Tree)
- 这里确立了优先级
- 乘方运算最靠前
- 先乘除后加减
- 有括号的要优先
- 这里确立了优先级
- 编译 得到 字节码 (bytecode)
- 字节码我们看不懂
- 所以反编译 得到 指令文件(opcode)
- 指令文件是基于python虚拟机的虚拟cpu的指令集
- 所以反编译 得到 指令文件(opcode)
- 先从 python3的最基础的
- 变量声明和赋值来看看
- python虚拟机是如何做的?🤔
- 变量声明和赋值来看看
- 看起来还挺明确的
- LOAD_CONST
- 把一个数字常量(CONST)1
- 装载(LOAD)进来
- STORE_NAME
- 把刚才装载进来的1
- 存储(STORE)
- 在a这个变量名(NAME)里面
- 具体二进制代码(opcode)什么样的呢?
- 先把var.py反编译
- 然后在
__pycache__
中观察对应的pyc文件- :%!xxd 转化为字节形态
- 可以看到那个数字常量1(红框)
- 前面的0x64是什么意思呢?
- 具体的数字来自于哪里呢?
- 由于a = 1 太特殊
- 我们来个不那么特殊的数字
- a = 0x23
- 2 句 python语句
- abc = 0x23
- efg = 0x45
- 各对应两条指令码(opcode)
- LOAD_CONST(装载常量)
- STORE_NAME(在变量名中存储)
- 可以从pyc的字节码中查看到
- 字符串类型呢?
- 还是1条python语句
- 对应2条指令码(opcode)
- 具体长啥样呢?
- 在字节码里面写得明明白白
- oeasy这个变量名
- o2z这个字符串
-
我们总结一下吧
-
尝试调试一下吧
- 我们一行行来
- 第1行执行之前(红色)
- a,b都不存在
- 第2行执行之前(绿色)
- a为1,b不存在
- 第2行执行之后(蓝色)
- a为1,b为2
- 结论
- 声明、赋值之前
- 不能使用变量
- 声明、赋值了之后
- 才能使用变量
- 可以看得清清楚楚
- 这个不难啊
- 这次我们调试和反编译了数据的定义
- 变量的定义和赋值对应两句指令
- LOAD_CONST
- STORE_NAME
- 变量在声明和赋值之前是不能被引用的
- 没有被声明的变量
- 也就没有生命
- 不能in the name of 那个变量
- 声明和赋值 用的就是字符串
- "a = 1"
- 我们可以直接
- 把字符串"a = 1" 当做参数
- 直接执行一下吗??🤔
- 把字符串"a = 1" 当做参数
- 我们下次再说!👋