我查看了以下帖子和博客,其中解释了使用函数执行此操作。我想知道它是否合法为类或对象方法做同样的事情? 将会欣赏适用于Python2的答案(尽管很好地了解它对Python3的作用)。
来自stackoverflow的来源:
Override module method where from...import is used和 Override a method at instance level
内容相似的博客:
https://tryolabs.com/blog/2013/07/05/run-time-method-patching-python/ http://igorsobreira.com/2011/02/06/adding-methods-dynamically-in-python.html
这段代码说明了我的意图以及我的尝试:
class Person:
def __init__(self, name):
self.name = name
class OtherPerson:
def __init__(self, name):
self.name = name
def do_something(self):
print self.name + '$$'
p = Person('alpha')
p.do_something = OtherPerson.do_something
# TypeError: unbound method do_something() must be called with
OtherPerson #instance as first argument (got nothing instead)
p.do_something()
op = OtherPerson('beta')
p.do_something = op.do_something
# output: 'beta$$' I would like to get 'alpha$$'
p.do_something()
尝试了以下来自@khelwood的建议:
Person.do_something = OtherPerson.do_something
#TypeError: unbound method do_something() must be called with OtherPerson instance as first argument (got nothing instead)
# Works if OtherPerson.do_something is staticmethod
p.do_something()
答案 0 :(得分:0)
如果OtherPerson.do_something是staticmethod:
,则可以这样做class Person(object):
def __init__(self, name):
self.name = name
class OtherPerson(object):
def __init__(self, name):
self.name = name
@staticmethod
def do_something(self):
print self.name + '$$'
p = Person('alpha')
Person.do_something = OtherPerson.do_something
p.do_something() #alpha$$
答案 1 :(得分:0)
关键是将正确的参数传递给方法。 让我们仔细看看你在第一时间得到的错误:
TypeError: unbound method do_something() must be called with
OtherPerson #instance as first argument (got nothing instead)
当你看OtherPerson.do_something
时,很明显它期望一个实例作为它的第一个参数。
所以现在p.do_something
引用OtherPerson.do_something
,它需要第一个参数。
因此,在当前状态下,正确的呼叫将是:
p.do_something(p)
当然,这不是很好,因为你必须指定实例两次。
那是因为该方法现在是 unbound :它不知道调用它的实例,即它不知道self
。
我提议的解决方案包括让p.do_something
引用使用 OtherPerson.fo_something
p
的函数>作为第一个参数。
我们有两个类Foo
和Bar
,定义如下:
class Foo:
def __init__(self, x):
self.x = x
def speak(self):
print("Foo says:", self.x)
class Bar:
def __init__(self, x):
self.x = x
def speak(self):
print("Bar says:", self.x)
假设您有foo
类的Foo
个实例。
现在,您希望动态覆盖其speak
方法,以便它调用Bar
。
您只需将foo.speak
重新分配给调用Bar.speak
的函数。
>>> foo = Foo(2)
>>> foo.speak()
Foo says: 2
>>> foo.speak = lambda: Bar.speak(foo)
>>> foo.speak()
Bar says: 2
你可以使它更通用。 为了举例,让我们编写一个函数,它接受一个实例,一个方法名和一个目标类,并用目标类':
覆盖实例的匹配方法。def override(instance, method_name, target_class):
class_method = getattribute(target_class, method_name)
def new_method(*args, **kwargs):
return class_method(instance, *args, **kwargs)
setattribute(instance, method_name, new_method)
您可以观察到相同的预期行为:
>>> foo = Foo(2)
>>> override(foo, "speak", Bar)
>>> foo.speak()
Bar says: 2