在Python中的运行时更改对函数的引用 [英] Change reference to function in run-time in Python

查看:194
本文介绍了在Python中的运行时更改对函数的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在运行时更改对另一个函数内部的函数的调用。

I need to change a call to a function inside another function during run-time.

请考虑以下代码:

def now():
    print "Hello World!"

class Sim:
    def __init__(self, arg, msg):
        self.msg = msg
        self.func = arg
        self.patch(self.func)

    def now(self):
        print self.msg

    def run(self):
        self.func()

    def patch(self, func):
        # Any references to the global now() in func
        # are replaced with the self.now() method.

def myfunc():
    now()

然后...

>>> a = Sim(myfunc, "Hello Locals #1")
>>> b = Sim(myfunc, "Hello Locals #2")
>>> b.run()
Hello Locals #2
>>> a.run()
Hello Locals #1

一个用户编写了代码, myfunc(),它会调用全局定义的函数 now(),但我无法对其进行编辑。但是我希望它调用 Sim 实例的方法。因此,我需要在运行时修补 myfunc()函数。

One user has written code, myfunc(), that makes a call to a globally defined function now() and I cannot edit it. But I want it to call the method of the Sim instance instead. So I would need to "patch" the myfunc() function in run-time.

我怎么去

一种可能的解决方案是按如下所示编辑字节码:
> http://web.archive.org/web/20140306210310/http://www.jonathon-vogel。 com / posts / patching_function_bytecode_with_python ,但我想知道是否有更简单的方法。

One possible solution is to edit the bytecode as done here: http://web.archive.org/web/20140306210310/http://www.jonathon-vogel.com/posts/patching_function_bytecode_with_python but I'm wondering if there is an easier way.

推荐答案

似乎。为此,您需要:


  • 使用以下方法创建 dict 子类: __ missing __ 方法来保存您的新值 now 。然后, __ missing __ 方法从通常的 globals()字典中获取词典中未包含的所有项目。

  • Create a dict subclass with a __missing__ method to hold your new value of now. The __missing__ method then grabs any items not in the dictionary from the usual globals() dict.

从现有的 myfunc()函数创建一个新的函数对象,保留其代码对象,但使用您创建的新字典

Create a new function object from the existing myfunc() function, keeping its code object but using the new dictionary you created for globals.

使用函数名称将新功能分配回全局中。

Assign the new function back into globals using its function name.

方法如下:

def now():
    print "Hello World!"

class NowGlobals(dict):
    def __init__(self, now, globals):
        self["now"] = now
        self.globals = globals
    def __missing__(self, key):
        return self.globals[key]

class Sim(object):
    def __init__(self, func):
        func = self.patch(func)
        self.func = func
    def now(self):
        print "Hello locals!"
    def patch(self, func):
        funcname   = func.__name__
        nowglobals = NowGlobals(self.now, func.func_globals)
        func = type(func)(func.func_code, nowglobals)
        globals()[funcname] = func
        return func

def myfunc():
    now()

sim = Sim(myfunc)
myfunc()

确实没有必要在课堂上,但我一直保持这种方式,因为那是您最初编写的方式。

There is really no need to have it in a class, but I've kept it that way since that's the way you wrote it originally.

如果 myfunc 在另一个模块中,您需要重写 Sim.patch()才能修补回该名称空间,例如 module.myfunc = sim.patch(module.myfunc)

If myfunc is in another module, you'll need to rewrite Sim.patch() to patch back into that namespace, e.g. module.myfunc = sim.patch(module.myfunc)

这篇关于在Python中的运行时更改对函数的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆