繁体   English   中英

python - 在实例级别动态覆盖方法并“更新”所有引用

[英]python - dynamically overriding a method at instance level and 'updating' all references

我想用 class B 中的方法覆盖 class A 实例的方法,但在某种程度上,所有对实例旧方法的引用(在覆盖方法之前进行)然后“链接”到新方法。 在代码中:

import types

class A:
    def foo(self):
        print('A')

class B:
    def foo(self):
        print('B')

class C:
    def __init__(self, a):
        self.func = a.foo

    def do_something(self):
        self.func()


a = A()
c = C(a)


method_name = 'foo'  # it has to be dynamic
new_method = getattr(B, method_name)
setattr(a, method_name, types.MethodType(new_method, a))


c.do_something()  # still prints A, I want it to print B now

我希望c.func在设置 a 的属性后保存来自 class B 的新方法(不对 c 对象执行任何操作)。

有没有办法设置实例 a 的属性,以便所有先前进行的引用然后引用新方法?

抱歉,如果这个问题有点愚蠢,我对此并不感兴趣。

你可以这样做,例如:

...
def retain(foo):
    return lambda *args, **kwargs: getattr(foo.__self__, foo.__name__)(*args, **kwargs)

class C:
    def __init__(self, a):
        self.func = retain(a.foo)
...

只是添加到亚历克斯的答案。 就我而言,所描述的动态部分来自对序列化和反序列化的需要。 为了序列化某些方法引用,我曾经使用func.__name__

但是, c.func.__name__只会使用 Alex 的方法返回<lambda> 我通过创建一个可调用的 class 来防止这种情况,该 class 使用保留 function 但单独存储方法的名称,这在我的情况下就足够了,因为它只是我需要序列化的一些特定引用。

def retain(foo):
    return lambda *args, **kwargs: getattr(foo.__self__, foo.__name__)(*args, **kwargs)

class M:
    def __init__(self, method):
        self.method_name = method.__name__
        self.method = retain(method)

    def __call__(self, *args, **kwargs):
        self.method(*args, **kwargs)

class A:
    def foo(self):
        print('A')

class B:
    def foo(self):
        print('B')

class C:
    def __init__(self, method):
        self.func = M(method)

    def do_something(self):
        self.func()

a = A()
c = C(a.foo)
setattr(a, method_name, types.MethodType(getattr(B, 'foo'), a))
c.do_something()  # now prints B

# when serializing
method_name = c.func.method_name

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM