首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有办法编写一个创建和执行代码的Python脚本?

有没有办法编写一个创建和执行代码的Python脚本?
EN

Stack Overflow用户
提问于 2012-12-10 12:27:39
回答 3查看 135关注 0票数 1

在Python中有没有办法在Python脚本中创建Python代码,然后执行/测试它?

我的函数具有以下类型的形式(作为示例)

代码语言:javascript
复制
def f(n):
    if n<=3: return [0, 0, 6, 12][n]
    return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)

但我希望能够动态创建这些类型的函数(或任何任意函数),然后在运行时测试它们的输出(而不是将此函数复制/粘贴到脚本中,然后手动测试它)。

不确定这是否有意义,如果需要,请要求详细说明。我已经研究了eval和exec,但无法让它们处理整个函数定义,只处理1+2等基本语句。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-10 12:44:29

有许多方法可以做到这一点。

如果函数不需要“跳出语言”就能被描述,你只需要定义一个局部函数并返回它,就像Blender的答案一样。当你认为你需要定义新函数时,这通常是你想要的(借用Blender的例子):

代码语言:javascript
复制
def make_func(a, b):
    def f(n):
        return n**a + b
    return f

有时,您可以做得更好,并将函数表示为数据。例如,如何创建任意多项式函数?你不需要这样做;你可以有一个通用的多项式函数,它接受一个系数列表和一个值,并对其求值;然后你需要做的就是创建系数列表。

事实上,我认为这就是你想要的。如你所说:

可以返回2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)一分钟,或者返回f(n-1) + 3*f(n-2)另一分钟,或者f(n-1)+f(n-2)+f(n-3)+f(n-4)+5*f(n-5),这取决于我需要它是什么。

这绝对可以表示为系数列表:

代码语言:javascript
复制
def make_recursive_func(coefficients, baseval):
    def f(n):
        if n < len(coefficients): return baseval[n]
        return sum(coefficient * f(n-i-1) for i, coefficient in enumerate(coefficients))
    return f

但是,如果您要对返回的函数所做的一切只是立即调用它,然后忘记它,那么编写单个eval_recursive_func(coefficients, baseval)可能会更简单。

有时-很少,但不是从来没有-你真的需要在飞行中执行代码。正如Himanshu所说,evalexec以及朋友是实现这一点的方法。例如:

代码语言:javascript
复制
newcode = '''
def f(n):
    if n<=3: return [0, 0, 6, 12][n]
    return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)
'''
exec(newcode)

现在已经定义了f函数,就像您刚刚定义的一样:

代码语言:javascript
复制
def f(n):
    if n<=3: return [0, 0, 6, 12][n]
    return 2*f(n-1) - 4*f(n-2) - 5*f(n-3) + 15*f(n-4)

在Py3中与在Py2中有一点不同,根据您想要在什么上下文中执行东西,或者您是否只想要它执行、计算、编译或像导入一样处理,等等,都有不同。但这是基本思想。

如果你想不出为什么要写第一个而不是第二个,那么你就不需要这个了。

如果你不知道如何动态地生成正确的字符串,你就不应该这么做。

而且,正如Ignacio Vazquez-Abrams指出的那样,如果这些函数可以从用户输入中构建出来,那么您需要做一些事情来验证它们是安全的,通常是通过迭代编译和遍历AST。

最后,您甚至很少需要使用new模块(和/或inspect)在其他函数对象的基础上动态创建新的函数对象(甚至是手工构造的字节码)。但是如果你需要知道如何做到这一点,你可能已经知道怎么做了。

票数 4
EN

Stack Overflow用户

发布于 2012-12-10 12:36:34

如果您的函数相似,您可以使用另一个函数创建它们:

代码语言:javascript
复制
def make_func(a, b):
    def f(n):
        return n**a + b

    return f

使用make_func转换此函数定义:

代码语言:javascript
复制
def g(n):
     return n**2 + 1

就是这样:

代码语言:javascript
复制
g = make_func(2, 1)

在您的例子中,类似这样的东西应该可以工作:

代码语言:javascript
复制
def create_f(start_condition, vars, coeff_pairs):
    def x(n):
        if n <= start_condition:
            return vars[n]

        result = 0.0

        for coeff, shift in coeff_pairs:
            result += coeff * x(n + shift)

        return result

    return x

您可以使用以下命令调用它:

代码语言:javascript
复制
f = create_f(3, [0, 0, 6, 12], [(2, -1), (-4, -2), (-5, -3), (15, -4)])

输出与您的硬编码函数的输出匹配。

票数 3
EN

Stack Overflow用户

发布于 2012-12-10 12:38:42

这是完全有道理的。Python甚至有一个显式用于此目的的set of modules。但是,在执行函数之前,请确保遍历AST并验证节点,以确保没有人偷偷进入其中的os.system('rm -rf /')

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13795010

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档