65

如何在 Python 中动态创建函数?

我在这里看到了一些答案,但我找不到一个可以描述最一般情况的答案。

考虑:

def a(x):
    return x + 1

如何即时创建这样的功能?我必须这样compile('...', 'name', 'exec')做吗?但那又如何呢?从编译步骤创建一个虚拟函数并替换其代码对象?

还是我应该使用types.FunctionType?如何?

我想自定义所有内容:参数的数量,它们的内容,函数体中的代码,结果,......

4

7 回答 7

38

使用exec

>>> exec("""def a(x):
...   return x+1""")
>>> a(2)
3
于 2012-07-02T10:25:45.577 回答
32

你看到了吗,是一个告诉你如何使用的例子types.FunctionType

例子:

import types

def create_function(name, args):
    def y(): pass

    y_code = types.CodeType(args,
                            y.func_code.co_nlocals,
                            y.func_code.co_stacksize,
                            y.func_code.co_flags,
                            y.func_code.co_code,
                            y.func_code.co_consts,
                            y.func_code.co_names,
                            y.func_code.co_varnames,
                            y.func_code.co_filename,
                            name,
                            y.func_code.co_firstlineno,
                            y.func_code.co_lnotab)

    return types.FunctionType(y_code, y.func_globals, name)

myfunc = create_function('myfunc', 3)

print repr(myfunc)
print myfunc.func_name
print myfunc.func_code.co_argcount

myfunc(1,2,3,4)
# TypeError: myfunc() takes exactly 3 arguments (4 given)
于 2012-07-02T11:15:04.873 回答
20

如果你需要从某个模板动态创建一个函数,试试这个:

def create_a_function(*args, **kwargs):

    def function_template(*args, **kwargs):
        pass

    return function_template

my_new_function = create_a_function()

在函数create_a_function()中,您可以控制选择哪个模板。内部函数function_template用作模板。创建者函数的返回值是一个函数。分配后,您将my_new_function用作常规函数。

通常,此模式用于函数装饰器,但在这里也可能很方便。

于 2015-11-11T16:30:59.747 回答
13

您可以为此使用 lambda。

a = lambda x: x + 1
>>> a(2)
3
于 2017-11-29T10:35:00.563 回答
6

这种方法怎么样?

在这个例子中,我在一个类中对一个变量 (x -> ax+b)参数化一阶函数:

class Fun: 
  def __init__(self, a,b):
    self.a, self.b = a,b

  def f(self, x):
    return (x*self.a + self.b)

 u = Fun(2,3).f

这里 u 将是函数 x->2x+3。

于 2015-07-17T10:36:28.313 回答
4

你可以这样做:

new_func='def next_element(x):\n  return x+1'
the_code=compile(new_func,'test','exec')
exec(the_code)
next_element(1)

它类似于以前的 exec 解决方案。

于 2020-02-04T13:22:15.197 回答
0

比 Berci 的答案更简单

def get_fn(a, b): # factory function
  def fn(): # result function
    print(a, b)
  return fn

fn = get_fn(1, 2)

fn()

这对于将变量转换为常量很有用(“动态函数的模板变量”)

于 2021-12-10T14:50:18.273 回答