在Python中的运行时更改对函数的引用 [英] Change reference to function in run-time in 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 ofnow
. The__missing__
method then grabs any items not in the dictionary from the usualglobals()
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屋!