如何在Python中动态创建函数?
我在这里看到了一些答案,但是没有找到一个可以描述最常见情况的答案。
考虑以下示例:
def a(x):
return x + 1
如何动态创建这样的函数?我需要使用compile('...', 'name', 'exec')
吗?但是然后呢?创建一个虚拟函数并将其代码对象替换为编译步骤中的代码对象吗?或者应该使用
types.FunctionType
?怎么用?我想自定义所有内容:参数数量、它们的内容、函数体中的代码、结果等等。
使用 exec
:
>>> exec("""def a(x):
... return x+1""")
>>> a(2)
3
NameError
错误,请考虑使用 locals().get('a')
。 - ניר你看到了 这个 吗?它是一个例子,告诉你如何使用 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)
func_Code
属性。 - Melendowski如果您需要从特定模板动态创建函数,请尝试使用以下代码:
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作为常规函数。
通常,这种模式用于函数修饰符,但在这里也可能很方便。
create_a_function
,参数作为参数。这样,属性可以在内部函数中作为普通变量使用,并且函数是分离的 :-) - Nilsa = lambda x: x + 1
>>> a(2)
3
a = eval("lambda x: x + 1")
,但结果是相同的。在我的情况下,我还为表达式提供数学函数,因此我还在评估和执行 lambda 的 Python 脚本中添加了 from math import *
。 - Chris Tophskigeneric['d'](3)
一样运行。 - endolith这种方法怎么样?
在这个例子中,我将一元一次函数(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。
functools.partial
应用于lambda表达式:u = partial(lambda a, b, x: x*a + b, 2, 3)
。 - cowbertnew_func='def next_element(x):\n return x+1'
the_code=compile(new_func,'test','exec')
exec(the_code)
next_element(1)
这与以前的exec解决方案类似。
def get_fn(a, b): # factory function
def fn(): # result function
print(a, b)
return fn
fn = get_fn(1, 2)
fn()
这对于将变量转换为常量(“动态函数的模板变量”)非常有用。
def create_function(function_name, function_arguments, function_code):
function_string = f"def {function_name}({function_arguments}): {function_code}"
exec(function_string)
return_value = eval(function_name)
return return_value
name = 'say_hello'
arguments = 'name'
code = 'print(f"Hello, {name}!")'
myfunc = create_function(name, arguments, code)
print(myfunc, type(myfunc))
myfunc('John Doe')
def dynamically_create_greeting(greet_style):
def inner(name):
print(f'{greet_style} {name}')
return inner
say_hello = dynamically_create_greeting(greet_style='hello')
say_hello('John')
say_hi = dynamically_create_greeting(greet_style='hi')
say_hi('John')
这将产生输出 >
你好 John
嗨 John
dynf = FunctionType(compile('def f(x): return x + 3', 'dyn.py', 'exec'), globals())
和print dynf(1)
会出现TypeError: '<module>() takes no arguments (1 given)'
错误。 - Ecir Hana