不幸的是,正常的东西types.MethodType
在这里不起作用,因为__call__
它是一种特殊的方法。
从数据模型:
类实例只有在类有__call__()
方法时才可调用;x(arguments) 是 的简写x.__call__(arguments)
。
这对于实际调用的内容有点模棱两可,但很明显您的类需要有一个__call__
方法。
您需要创建某种 hack:
class Foo(object):
def __init__(self):
pass
def f(self):
print "f"
def g(self):
print "g"
def __call__(self):
return self.__call__()
f = Foo()
f.__call__ = f.f
f()
g = Foo()
g.__call__ = g.g
g()
__call__
不过要小心,如果在尝试调用它之前没有在实例上设置 a ,它将导致无限递归。
请注意,我实际上不建议调用您 rebind 的魔法属性__call__
。这里的重点是证明 python 可以转换f()
为: f.__class__.__call__(f)
,因此您无法在每个实例的基础上对其进行更改。__call__
无论您做什么,都会调用该类-您只需要做一些事情来改变该类的__call__
每个实例的行为,这很容易实现。
您可以使用 setter 类型的东西在您的类上实际创建方法(而不是简单的函数)——当然这可以变成一个属性:
import types
class Foo(object):
def __init__(self):
pass
def f(self):
print "f"
def g(self):
print "g"
def set_func(self,f):
self.func = types.MethodType(f,self)
def __call__(self,*args,**kwargs):
self.func(*args,**kwargs)
f = Foo()
f.set_func(Foo.f)
f()
def another_func(self,*args):
print args
f.set_func(another_func)
f(1,2,3,"bar")