猴子补丁父类

时间:2018-04-12 16:10:12

标签: python-3.x

我必须关注模块:

class A():
    a = 1
class B(A):
    b = 2

在另一个文件中,我想替换A类(like here):

import module
class C():
    c = 3
module.A = C

创建B对象时,它应该立即从C继承,并且具有.c属性,但是,它不会:

assert module.B().c == 3

但是,这会引发:AttributeError: 'B' object has no attribute 'c'

如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

变量是对象的引用。重新分配变量时,它不会影响前一个对象,除非它的引用计数变为零并且它被删除。在你的情况下

class A:
    a = 1
class B(A):
    b = 2

B获取当时恰好分配给A的类对象,并将其用作父对象。只要Bsuper用于将来对其父级的引用,B就不会再次触及A变量。你对A的重新分配没有任何区别。

但你确实说过Monkey Patch,这仍然可行。只需将东西放到原来的A类上,所有的继承者都会看到它:

import module
module.A.c = 3
assert module.B().c == 3

您还可以添加或替换方法

import module

def d(self):
    return 4

module.A.d = d
assert module.B().d() == 4

或者,如果您只想对某些 A的继承者进行此更改,请考虑使用mixins What is a mixin, and why are they useful?

答案 1 :(得分:0)

post of tdelaney中的想法可以自动化:

def replace_class(oldcls, newcls):
    '''Adds/replaces the contents for oldcls with newcls, leaving 
    references to oldcls in-place. Usefull for monkey patching'''
    for key, val in newcls.__dict__.items():
        if key != '__dict__':
            setattr(oldcls, key, val)

现在可行了

replace_class(module.A, C)
module.B().c == 2