python的eval

eval(X, type("_Dummy", (dict,), {'__getitem__': lambda name, value: name}))

这段代码最重要的一个应用是可以格式化非标准的JSON数据,比如

X = { key: "value" }
eval(X, type("", (dict,), {'__getitem__': lambda s, n: n})())

这样可以转化成标准字典

那么这一句神奇的东西该怎么解释呢?
首先type在这里充当的不是返回类型的作用,这里作为一个class constructor的存在,第一个参数是类名,第二个参数为类的基类,第三个参数为一个字典,表示这个类的成员和方法。
那么,eval(X, type("", (dict,), {'__getitem__': lambda s, n: n})())就是创建了一个临时的 _Dummy 类,上面的语句规约为

eval(X, _Dummy)

那么eval的第二个的参数什么意思呢?

>>> help(eval)
eval(...)
eval(source[, globals[, locals]]) -> value

Evaluate the source in the context of globals and locals.
The source may be a string representing a Python expression
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.

我们就知道了,这个求X的值里涉及到的变量 key 这个变量会放到 _Dummy() 里去求,则会等价于调用 _Dummy()['key'],此时就会调用到我们的 __getitem__,这个方法我们定义了返回 name 也就是 “key” ,所以,一个变量名在这里就转换成了字符串。

但是eval毕竟是eval,在使用它的时候永远不要相信用户输入的参数,无论哪个语言的eval,滥用的结果都是惨重的。比如说:

福尔摩喵 (大喵神) 给出了一个 Referencence,写出了如何构造有害的东西来搞事情。

这里有篇文章涉及 Python 解释器安全 Paving the Way to Securing the Python Interpreter

还有个Pypy的sandbox Pypy feature#sandboxing

1 thought on “python的eval”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s