Python中的Python动态函数

时间:2013-05-14 07:56:18

标签: python python-2.7 metaprogramming dynamic-function

我遇到了一些相关的答案,但不是我想要的。

以下是我现在的代码:

code_str = """
print "this is my global x = " + x
print "And another line is done"
"""

x = 'mystery'

func_template = lambda p: None

func_template.__code__ = compile(code_str, '<string>', 'exec')
func_template() # this executes fine and also has access to x, which i do need.
# func_template('param') # This raises: TypeError: <module>() takes no arguments (1 given)

一些背景; code_str将来自一个数据库,我需要在dict中存储许多函数,所以我可以通过名字调用任何一个函数,如下所示:

all_funcs = {}

# Assuming db_result returns a list of name, code tuples from the databse

for name, code in db_result:
    all_funcs[name] = my_compile(code)

如果我知道名字,我想用我想要的参数调用所需的函数:

result = all_funcs[by_name](arg1, arg2)

编辑数据库是受信任的,因此我不需要对恶意代码进行补充或担心。

1 个答案:

答案 0 :(得分:1)

如果替换lambda的__code__对象,则基本上重新定义了该函数。新的argcount由__code__.co_argcount确定,因此lambda之前使用的参数不重要。

如果要将参数传递给已编译的代码,可以直接尝试eval代码对象,并在locals dictionaray中传递参数:

code_str = """
print "this is my global x = " + x
print "And another line is done"
print param
"""

compiled = compile(code_str, "<string>", "exec")
func_template = lambda p=None: eval(compiled, globals(), {'param': p})

x = "1"
func_template()
func_template("2")

这种方式显然只能传递关键字参数,不可能使用位置参数。你也可以使用

func_template = lambda **kwargs: eval(compiled, globals(), **kwargs)

直接传递给你的函数的关键字参数。

如果您需要函数的返回值,那么您需要以'eval'模式编译代码,这意味着您必须将代码限制为表达式而不能包含语句。< / p>