【问题标题】:Replace method with method of instance of different class用不同类实例的方法替换方法
【发布时间】:2019-11-08 16:11:57
【问题描述】:

我只是试图用一些具有相似父类的类创建一个系统,它在它们之间动态分配它们的方法,它看起来像一个函数“transform(from, to)”,它的作用类似于 from.foo = to。呵呵

所以,你看,我的问题对于 Python 来说很困难,所以我正在寻求帮助

我的第一次尝试是

def transform(a, b):
    a.foo = b.foo


class A:
    def foo(self):
        pass


class B(A):
    def foo(self):
        print("bar")
        transform(self, C())


class C(A):
    def foo(self):
        print("foo")
        transform(self, B())

b = C()
b.foo()
b.foo()
b.foo()
b.foo()

我想从中得到一些像

foo
bar
foo
bar

但我明白了

foo
bar
bar
bar

最有趣的时刻是第一次转换成功,但接下来。


我的下一个尝试是

class A:
    def foo(self):
        pass

    def transform(self, to):
        self.foo = to.foo


class B(A):
    def foo(self):
        print("bar")
        self.transform(C())


class C(A):
    def foo(self):
        print("foo")
        self.transform(B())

b = C()
b.foo()
b.foo()
b.foo()
b.foo()

我得到了同样的结果。您知道如何管理此转换吗?

【问题讨论】:

    标签: python class methods


    【解决方案1】:

    在您的代码中,它首先运行a.foo = b.foo,其中a 是在b = C() 创建的对象,b 是在B() 创建的对象。然后当下次运行a.foo() 时,它运行B 的foo(self),其中self 是那个B() 对象。在那里,它运行transform(self, C()),其中self 仍然是使用B() 创建的对象,不是b 的对象。基本上,b 只修改一次,就再也不会修改了。

    相反,您应该在将foob.foo.__func__ 分配给另一个之前获取未绑定的函数对象,否则foo 中的self 将引用对象B() 而不是b .然后,您可以使用types.MethodType 将其绑定回目标对象:

    from types import MethodType
    
    def transform(a, b):
        a.foo = MethodType(b.foo.__func__, a)
    
    class A:
        def foo(self):
            pass
    
    
    class B(A):
        def foo(self):
            print("bar")
            transform(self, C())
    
    
    class C(A):
        def foo(self):
            print("foo")
            transform(self, B())
    
    b = C()
    b.foo()
    b.foo()
    b.foo()
    b.foo()
    
    foo
    bar
    foo
    bar
    

    你的第二次尝试也通过做同样的事情来解决:

    from types import MethodType
    
    class A:
        def foo(self):
            pass
    
        def transform(self, to):
            self.foo = MethodType(to.foo.__func__, self)
    
    
    class B(A):
        def foo(self):
            print("bar")
            self.transform(C())
    
    
    class C(A):
        def foo(self):
            print("foo")
            self.transform(B())
    
    b = C()
    b.foo()
    b.foo()
    b.foo()
    b.foo()
    
    foo
    bar
    foo
    bar
    

    【讨论】:

    • 所以他在两次调用之间更改了 self 对象,这就是它不起作用的原因?
    • @geckos 是的,在asker的原始代码中,第一次运行a.foo = b.foo,其中a是在b = C()创建的对象,b是在B()创建的对象- - 那么当下次运行a.foo() 时,它将运行B 的foo(self),其中self 是那个B() 对象。在那里,它将运行transform(self, C()),其中selfB() 创建的对象。基本上,b 只修改过一次,然后就再也没有修改过。
    • 感谢您的解释!
    猜你喜欢
    • 2012-02-27
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多