从字符串创建函数对象
问题:有没有办法在Python中用字符串来创建一个函数对象?
信息:我正在做一个项目,数据存储在sqlite3服务器后台。这个没什么特别的。通常情况下,DAL类是通过代码生成来完成的,因为代码实在是太简单了。但这让我想到一个主意。在Python中,当找不到某个属性时,如果你定义了一个叫__getattr__
的函数,它会在出错之前先调用这个函数。所以我想,通过一个解析器和逻辑树,我可以在第一次调用时动态生成我需要的代码,然后把这个函数对象保存为一个本地属性。例如:
DAL.getAll()
#getAll() not found, call __getattr__
DAL.__getattr__(self,attrib)#in this case attrib = getAll
##parser logic magic takes place here and I end up with a string for a new function
##convert string to function
DAL.getAll = newFunc
return newFunc
我试过使用compile函数,但exec和eval在实现这种功能上远远不够理想。我需要一些可以处理多行函数的东西。除了这些方法,还有没有其他办法可以做到这一点,而不需要把它写入磁盘?我再次强调,我想要动态创建一个函数对象。
附注:是的,我知道这样做有很大的安全和稳定性问题。是的,我知道这是一种效率极低的做法。我在乎吗?不在乎。这只是一个概念验证。“Python能做到吗?它能动态创建一个函数对象吗?”这是我想知道的,而不是一些更好的替代方案。(不过在你回答完这个问题后,欢迎补充更好的替代方案)
3 个回答
如果只是想验证一个概念的话,使用 eval 和 exec 是可以的。你也可以用 pickle 字符串、yaml 字符串,或者任何你决定写构造函数的东西来实现这个。
你不能这样做吗?
>>> def func_builder(name):
... def f():
... # multiline code here, using name, and using the logic you have
... return name
... return f
...
>>> func_builder("ciao")()
'ciao'
基本上,就是直接组装一个真正的函数,而不是先组装一个字符串,然后再试着把它编译成一个函数。
下面的代码会把你在字符串中定义的符号放到一个字典 d
里:
d = {}
exec "def f(x): return x" in d
现在 d['f']
是一个函数对象。如果你想在字符串中的代码里使用你程序里的变量,可以通过 d
来传递这些变量:
d = {'a':7}
exec "def f(x): return x + a" in d
现在 d['f']
是一个动态绑定到 d['a']
的函数对象。当你改变 d['a']
的值时,d['f']()
的输出也会随之改变。