【问题标题】:Inject function calls into python function将函数调用注入python函数
【发布时间】:2021-03-08 17:56:05
【问题描述】:

假设我在一个模块中有一些简单的 python 函数

def f(x):
    print(x)

这个函数只是打印它的参数。但是,我想修改这个函数或类方法,这取决于它实际上是什么。

我还有第二个功能:

def g(x):
    x.append(1)

它操纵输入参数(可能是list)并附加一些项目。现在,我想将对 g 的调用注入到 f 中,以便后者的行为类似于

def f_patched(x):
    g(x)
    print(x)

显然,这可以通过猴子修补f 来完成。然而,这并不总是实用的,特别是如果f 是一些更大的函数,因为我必须复制大部分代码(如果这甚至是合法的)只是为了更改一行。通过注入对g 的调用给定一些参考,例如“在第 XXX 行之后”或“在指令 XXX 之后”,我可以轻松地修改f 的行为。

有没有办法将函数调用注入到不同的函数中?你可以假设,我知道f 的来源,或者至少f 是众所周知的,并且不变使这成为可能。

【问题讨论】:

  • 你可能可以拼接字节码或其他东西,但我很困惑你为什么想要这个。
  • 你为什么不直接定义和使用像f_patched这样的函数?
  • "通过注入给定引用的调用 tog,例如“在第 XXX 行之后”或“在指令 XXX 之后”,我可以轻松地修改 f 的行为。"没有实际的方法可以做到这一点。
  • 提供一些上下文:matplotlib 中有一些函数可以很容易地通过几行额外的代码进行更多的自定义......

标签: python python-3.x monkeypatching


【解决方案1】:

也许您可以在程序的早期(即在它第一次调用之前)重新定义该函数以将其替换为您的修补版本:

import myModule

# before this f() is the original

old_f = myModule.f           # capture a reference to the original
def f_patched(x):
    g(x)                     # inject your code
    return old_f(x)          # use the original
myModule.f = f_patched       # replace the original

# from here onward, f() will be the patched version that calls the original

【讨论】:

  • 这正是 OP 所指的猴子补丁
  • 确实,我想我有点模仿这个问题。我的意思是说明没有必要“复制大部分代码”。
  • 是的,好吧,但似乎 OP 不只是想做这么简单的事情,他们想要“通过注入一个给定参考的调用 tog,例如“在第 XXX 行之后”或“在指令 XXX" 我可以很容易地修改 f 的行为。"
  • 当且仅当代码需要注入之前 f 所做的所有其他事情时才有效。
  • 同意,在原始代码之前或之后,但原始代码中的任何内容都需要完全了解该代码,并且不得进行任何不可告人的(破坏性)修改。此时,在大多数情况下,重写可能会更安全。
猜你喜欢
  • 2016-06-04
  • 1970-01-01
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 2016-11-11
  • 2012-01-27
  • 1970-01-01
  • 2012-11-05
相关资源
最近更新 更多