Python 动态创建函数【转】

知乎上也有相似的问题

偶然碰到一个问题,初想是通过动态创建Python函数的方式来解决,于是调研了动态创建Python函数的方法。

定义lambda函数

在Python中定义lambda函数的写法很简单,

func = lambda: "foobar"

可以认为lambda函数是最常用的一种方式。

定义局部函数

Python中函数可以在代码块中进行定义,比如decorator就是通过这种方式实现的,

def decorator(func):
    def _(*args, **kwargs):
        return func(*args, **kwargs)
    return _

通过types.FunctionType创建函数

Python标准库中的types.FunctionType也可以用于创建函数,常见有如下两种使用方式,

  • 从已有函数构建心函数
def foobar():
    return "foobar"

dynamic = types.FunctionType(foobar.__code__, {})
  • 配合compile函数构建
module_code = compile('def foobar(): return "foobar"', '', 'exec')
function_code = [c for c in module_code.co_consts if isinstance(c, types.CodeType)][0]
foobar = types.FunctionType(function_code, {})
print foobar()

通过ast创建函数

除了通过compile()直接编译字符串代码之外,Python中也可以直接创建ast相关对象,最终再通过compile(), types.FunctionType进行构建,

from ast import *
import types

function_ast = FunctionDef(
    name='foobar',
    args=arguments(args=[], vararg=None, kwarg=None, defaults=[]),
    body=[Return(value=Num(n=42, lineno=1, col_offset=0), lineno=1, col_offset=0)],
    decorator_list=[],
    lineno=1,
    col_offset=0
)
module_ast = Module(body=[function_ast])
module_code = compile(module_ast, "<>", "exec")
function_code = [c for c in module_code.co_consts if isinstance(c, types.CodeType)][0]
foobar = types.FunctionType(function_code, {})
print foobar()

通过eval创建函数

最后还有一个eval函数,

foobar = eval('lambda: "foobar"')

在eval函数中不能直接通过def定义函数,所以尝试定义lambda函数进行替代。

其它方法

除了上面罗列的还有些旁的方法,比如,

将函数定义写入到单独的py文件中,而后通过 __import__ 操作导入模块来获取定义的函数。

总结

绝大部分应用场景下通过lambda或decorator就足以应付需求了,不过动态语言的函数就是真的想动态的搞,也是能找到方法的。

 

原文:http://soliloquize.org/2015/07/02/Python动态创建函数的几种方法/

 

posted @ 2015-12-22 18:11  高山流的不是水  阅读(8587)  评论(0编辑  收藏  举报