假设我在Python中有一个带参数的任意函数f。
def f(x): return 2*x
现在假设我想要一个函数,该函数需要一个函数并返回相同的函数,但沿y轴翻转(如果已绘制)。
显而易见的方法是
def reverse_fn(f): return lambda x, funct=f: funct(-x)
但是,像这样堆叠函数修改函数会在一段时间后破坏最大递归深度,因为结果只是一个调用了另一个函数的函数,而该函数又一直调用更多函数。
在Python中制作函数修改函数的最佳方法是什么,可以在不占用过多调用栈或嵌套函数的情况下反复使用?
最佳答案
一种方法是编辑函数的字节码。这是一项非常先进的技术,而且非常脆弱。因此,请勿将其用于生产代码!
就是说,那里有一个模块,可以精确实现所需的编辑类型。它被称为bytecodehacks
,于2000年4月1日首次发布(是的,这是愚人节的玩笑,但完全是功能性的笑话)。我安装的Python 2.7.6稍晚一些版本(自2005年起)运行良好;抓住它from CVS并照常运行setup.py
。 (不要使用April2000版本;它不能在较新的Python上运行)。bytecodehacks
基本上实现了许多实用程序例程,这些例程可以编辑一段代码(一个函数,模块,甚至一个函数中的单个块)的字节码。例如,您可以使用它来实现宏。为了修改功能,inline
工具可能是最有用的。
这是使用reverse_fn
实现bytecodehacks
的方法:
from bytecodehacks.inline import inline
def reverse_fn(f):
def g(x):
# Note that we use a global name here, not `f`.
return _f(-x)
return inline(g, _f=f)
就这样!
inline
负责将函数f
“内联”到g
主体中的繁琐事务。实际上,如果f(x)
是return 2*x
,则从reverse_fn(f)
返回的函数将等同于return 2*(-x)
(其中将不包含任何函数调用)。现在,
bytecodehacks
的局限性在于变量重命名(在extend_and_rename
中的inline.py
中)有点愚蠢。因此,如果您连续应用reverse_fn
1000次,由于局部变量名称的大小将开始爆炸,您的速度将大大降低。我不确定如何解决此问题,但是如果您这样做,它将大大提高重复内联函数的性能。