python—在实例级别和';更新';所有参考资料

python—在实例级别和';更新';所有参考资料,python,setattr,Python,Setattr,我想用类B中的方法重写类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_somet

我想用类B中的方法重写类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的属性后保存类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)
...

您可以这样做,例如:

...
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.\uu\u name\uu

但是,
c.func.\uuuuu name\uuuu
只会使用Alex的方法返回
。我通过创建一个可调用类来防止这种情况,该类使用retain函数,但单独存储方法的名称,在我的例子中,这就足够了,因为它只是一些需要序列化的特定引用

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

只是补充亚历克斯的答案。 在我的例子中,所描述的动态部分来自对序列化和反序列化的需求。为了序列化某些方法引用,我使用
func.\uu\u name\uu

但是,
c.func.\uuuuu name\uuuu
只会使用Alex的方法返回
。我通过创建一个可调用类来防止这种情况,该类使用retain函数,但单独存储方法的名称,在我的例子中,这就足够了,因为它只是一些需要序列化的特定引用

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

请注意,
c
必须知道
a
,而不仅仅是
a.foo
。这是您的设置中可以接受的更改吗?不一定。但在某些情况下,这可能会有所帮助。这取决于实现。请注意,
c
必须知道
a
,而不仅仅是
a.foo
。这是您的设置中可以接受的更改吗?不一定。但在某些情况下,这可能会有所帮助。这要看执行情况。哦,这真的很好!非常感谢你。我会尝试一些东西,但对我来说似乎很可靠。我只是发现了一个小问题。在我的软件中的其他地方,我试图访问引用的序列化方法的名称(
c.func.\uuuu name\uuuu
),该方法现在只返回。有什么想法吗?哦,这真是太好了!非常感谢你。我会尝试一些东西,但对我来说似乎很可靠。我只是发现了一个小问题。在我的软件中的其他地方,我试图访问引用的序列化方法的名称(
c.func.\uuuu name\uuuu
),该方法现在只返回。有什么想法吗?