python - 内联 Python 函数

标签 python inline abstract-syntax-tree compiler-optimization

在 C 程序中,内联函数是一种相当直观的优化。如果内联函数的主体足够小,您最终将跳转保存到函数和堆栈帧的创建,并将返回值存储在函数结果将被存储的任何位置,跳转到内联函数“主体”的末尾"而不是长跳转到返回指针。

我有兴趣在 Python 中做同样的事情,将两个 python 函数转换为另一个有效的 python 函数,其中第一个函数“内联”到第二个函数中。一个理想的解决方案可能如下所示:

def g(x):
    return x ** 2

def f(y):
    return g(y + 3)

# ... Becomes ...

def inlined_f(y):
    return (y + 3) ** 2

显然,在像 Python 这样动态的语言中,自动执行此操作并非易事。我想出的最好的通用解决方案是使用 dict 来捕获传递给函数的参数,将函数体包装在一个迭代 for 循环中,使用 break 跳转到函数的末尾,并将参数的使用替换为参数字典中的索引。结果如下所示:

def inlined_f(y):
    _g = dict(x=y + 3)
    for ____ in [None]:
        _g['return'] = _g['x'] ** 2
        break
    _g_return = _g.get('return', None)
    del _g
    return _g_return

我不在乎它丑陋,但我在意它不支持从循环内返回。例如:

def g(x):
    for i in range(x + 1):
        if i == x:
            return i ** 2
    print("Woops, you shouldn't get here")

def inlined_f(y):
    _g = dict(x=y + 3)
    for ____ in [None]:
        for _g['i'] in range(_g['x'] + 1):
            if _g['i'] == _g['x']:
                _g['return'] _g['i'] ** 2
                break  # <-- Doesn't exit function, just innermost loop
        print("Woops, you shouldn't get here")
    _g_return = _g.get('return', None)
    del _g
    return _g_return

我可以采取什么方法来避免需要使用 break 来“跳出”内联函数的主体?我也愿意接受一种总体上更好的通用方法,我可以采用这种方法将一个 Python 函数内联到另一个函数中。

作为引用,我在 AST(抽象语法树)级别工作,因此使用经过解析的 Python 代码;显然,除了字面值之外,我不知道在执行此转换时任何东西会有什么值或类型。生成的内联函数的行为必须与原始函数相同,并且必须支持调用函数时通常可用的所有功能。这在 Python 中甚至可能吗?


编辑:我应该澄清一下,因为我使用了“优化”标签,我实际上对性能提升并不感兴趣。生成的代码不需要更快,它只是不能调用内联函数,同时仍具有相同的行为。您可以假设这两个函数的源代码都可以作为有效的 Python 使用。

最佳答案

我看到在源代码级别唯一合理的方式,简化:

  • 将源代码解析成一些 AST(或者只使用 the built-in AST )。
  • 复制代表函数主体的子树。
  • 重命名子树中的变量,例如通过添加一个唯一的前缀。
  • 在调用点,使用函数的新变量名称将所有传递的参数替换为赋值。
  • 删除调用并将其替换为您准备好的函数体。
  • 将 AST 序列化回源。

真正的问题是什么:

  • 生成器函数;只是不要内联它们。
  • try/finally 下返回需要运行 finally 部分。可能很难正确重写;恕我直言,最好不要穿内衬。
  • 从需要运行 __exit__ 部分的上下文管理器中返回。虽然并非不可能,但重写保留语义也很棘手;也可能最好不要内联。
  • 中间函数返回,尤其是从多个循环结构中返回。您可能需要用一个额外的变量替换它们,并将其线程化到每个 while 语句的每个条件中,并且可能需要向 for 语句添加一个条件中断。同样,并非不可能,但最好不要内联。

关于python - 内联 Python 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50141784/

相关文章:

c++ - Bison/Flex 教程,包括 C++、AST 和可重入词法分析器和解析器

java - 在 eclipse jdt AST 中创建类型绑定(bind)

python - 绘制图像的 2D FFT

python - 在 JSON 数组中搜索值

python - 在没有计数的情况下计算两个列表之间的频率的替代方法

f# - 在F#中,是否可以使用tryParse函数来推断目标类型

c++ - 派生类中虚函数调用的优化

python - 如何从 Ableton Live 控制表面脚本将 MIDI 数据发送到我的 Arduino 板

c++ - 为什么不能将 static constexpr 成员变量传递给函数?

python - 如何提取Python源代码中使用的所有函数和API调用?