mirror of
https://github.com/apachecn/ailearning.git
synced 2026-02-03 10:24:39 +08:00
224 lines
2.1 KiB
Markdown
224 lines
2.1 KiB
Markdown
# 动态编译
|
||
|
||
## 标准编程语言
|
||
|
||
对于 **C** 语言,代码一般要先编译,再执行。
|
||
|
||
```py
|
||
.c -> .exe
|
||
```
|
||
|
||
## 解释器语言
|
||
|
||
shell 脚本
|
||
|
||
```py
|
||
.sh -> interpreter
|
||
```
|
||
|
||
## Byte Code 编译
|
||
|
||
**Python, Java** 等语言先将代码编译为 byte code(不是机器码),然后再处理:
|
||
|
||
```py
|
||
.py -> .pyc -> interpreter
|
||
```
|
||
|
||
## eval 函数
|
||
|
||
```py
|
||
eval(statement, glob, local)
|
||
```
|
||
|
||
使用 `eval` 函数动态执行代码,返回执行的值:
|
||
|
||
In [1]:
|
||
|
||
```py
|
||
a = 1
|
||
|
||
eval("a+1")
|
||
|
||
```
|
||
|
||
Out[1]:
|
||
|
||
```py
|
||
2
|
||
```
|
||
|
||
可以接收明明空间参数:
|
||
|
||
In [2]:
|
||
|
||
```py
|
||
local = dict(a=2)
|
||
glob = {}
|
||
eval("a+1", glob, local)
|
||
|
||
```
|
||
|
||
Out[2]:
|
||
|
||
```py
|
||
3
|
||
```
|
||
|
||
这里 `local` 中的 `a` 先被找到。
|
||
|
||
## exec 函数
|
||
|
||
```py
|
||
exec(statement, glob, local)
|
||
```
|
||
|
||
使用 `exec` 可以添加修改原有的变量。
|
||
|
||
In [3]:
|
||
|
||
```py
|
||
a = 1
|
||
|
||
exec("b = a+1")
|
||
|
||
print b
|
||
|
||
```
|
||
|
||
```py
|
||
2
|
||
|
||
```
|
||
|
||
In [4]:
|
||
|
||
```py
|
||
local = dict(a=2)
|
||
glob = {}
|
||
exec("b = a+1", glob, local)
|
||
|
||
print local
|
||
|
||
```
|
||
|
||
```py
|
||
{'a': 2, 'b': 3}
|
||
|
||
```
|
||
|
||
执行之后,`b` 在 `local` 命名空间中。
|
||
|
||
## 警告
|
||
|
||
动态执行的时候要注意,不要执行不信任的用户输入,因为它们拥有 `Python` 的全部权限。
|
||
|
||
## compile 函数生成 byte code
|
||
|
||
```py
|
||
compile(str, filename, mode)
|
||
```
|
||
|
||
In [5]:
|
||
|
||
```py
|
||
a = 1
|
||
c = compile("a+2", "", 'eval')
|
||
|
||
eval(c)
|
||
|
||
```
|
||
|
||
Out[5]:
|
||
|
||
```py
|
||
3
|
||
```
|
||
|
||
In [6]:
|
||
|
||
```py
|
||
a = 1
|
||
c = compile("b=a+2", "", 'exec')
|
||
|
||
exec(c)
|
||
b
|
||
|
||
```
|
||
|
||
Out[6]:
|
||
|
||
```py
|
||
3
|
||
```
|
||
|
||
## abstract syntax trees
|
||
|
||
In [7]:
|
||
|
||
```py
|
||
import ast
|
||
|
||
```
|
||
|
||
In [8]:
|
||
|
||
```py
|
||
tree = ast.parse("a+2", "", "eval")
|
||
|
||
ast.dump(tree)
|
||
|
||
```
|
||
|
||
Out[8]:
|
||
|
||
```py
|
||
"Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Num(n=2)))"
|
||
```
|
||
|
||
改变常数的值:
|
||
|
||
In [9]:
|
||
|
||
```py
|
||
tree.body.right.n = 3
|
||
|
||
ast.dump(tree)
|
||
|
||
```
|
||
|
||
Out[9]:
|
||
|
||
```py
|
||
"Expression(body=BinOp(left=Name(id='a', ctx=Load()), op=Add(), right=Num(n=3)))"
|
||
```
|
||
|
||
In [10]:
|
||
|
||
```py
|
||
a = 1
|
||
c = compile(tree, '', 'eval')
|
||
|
||
eval(c)
|
||
|
||
```
|
||
|
||
Out[10]:
|
||
|
||
```py
|
||
4
|
||
```
|
||
|
||
安全的使用方法 `literal_eval` ,只支持基本值的操作:
|
||
|
||
In [11]:
|
||
|
||
```py
|
||
ast.literal_eval("[10.0, 2, True, 'foo']")
|
||
|
||
```
|
||
|
||
Out[11]:
|
||
|
||
```py
|
||
[10.0, 2, True, 'foo']
|
||
``` |