从字符串创建函数对象

12 投票
3 回答
21425 浏览
提问于 2025-04-16 18:10

问题:有没有办法在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 个回答

0

如果只是想验证一个概念的话,使用 eval 和 exec 是可以的。你也可以用 pickle 字符串、yaml 字符串,或者任何你决定写构造函数的东西来实现这个。

2

你不能这样做吗?

>>> 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'

基本上,就是直接组装一个真正的函数,而不是先组装一个字符串,然后再试着把它编译成一个函数。

27

下面的代码会把你在字符串中定义的符号放到一个字典 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']() 的输出也会随之改变。

撰写回答