【问题标题】:Python dynamic functions from strings来自字符串的 Python 动态函数
【发布时间】:2013-05-14 07:56:17
【问题描述】:

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

这是我现在拥有的代码:

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)

编辑:数据库是可信的,所以我不需要清理或担心恶意代码。

【问题讨论】:

    标签: python python-2.7 metaprogramming dynamic-function


    【解决方案1】:

    如果替换 lambda 的 __code__ 对象,则基本上是重新定义了函数。新的 argcount 由 __code__.co_argcount 确定,因此 lambda 之前使用了哪个或多少个参数都没有关系。

    如果你想将参数传递给你的编译代码,你可以尝试直接eval你的代码对象,在locals字典中传递你的参数:

    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' 模式下编译代码,这意味着您必须将代码限制为表达式并且不能有语句。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-28
      • 2016-05-30
      • 2015-04-11
      • 2015-04-06
      • 2020-09-08
      • 1970-01-01
      • 2013-02-18
      相关资源
      最近更新 更多