Override used classes in parent class

a 夏天 提交于 2019-12-23 12:16:45

问题


Suppose there is a class NiceClass using some other class LesserClass in a place I can't edit

# NiceClass.py

class LesserClass:
    ...
    # stuff
    ...

class NiceClass:
    ...
    # Lots of use of lesser class in here...
    ...

Now I want to use my own class MyLesserClass instead of LesserClass everywhere in an inherited version of NiceClass

# MyNiceClass.py

from NiceClass import NiceClass
from NiceClass import LesserClass as oldLesserClass

class LesserClass(oldLesserClass):
    ...
    # Some extra stuff
    ...

class MyNiceClass(NiceClass):
    ...
    # Everywhere LesserClass was used I now want to use MyLesserClass
    ...

But all the non-overridden methods in MyNiceClass will use the LesserClass from the old NiceClass.py.

Everything would work as I want if I just copy-pasted in the whole definition of NiceClass into MyNiceClass.py.

It's like I just want to inherit the source code and not the whole namespace. Maybe inheritence is the wrong way?


回答1:


I hope this is only limited to methods under NiceClass using the class LesserClass.

Now if you want the methods inside MyNiceClass to use MyLesserClass instead of LesserClass then you could update the __globals__ dict of those methods and make the name 'LesserClass' point to MyLesserClass.

Here's a simple example demonstrating the same by overriding __getattribute__:

class A:
    a = 'A.a'
    b = 'A.b'


class B:
    def func_a(self):
        print(A.a)

    def func_b(self):
        print(A.b)


class C:
    a = 'C.a'
    b = 'C.b'


class D(B):
    def func_a(self):
        print(C.a)

    def __getattribute__(self, attr):
        value = object.__getattribute__(self, attr)
        if callable(value):
            value = update_namespace(value, {'old': {'name': 'A', 'obj': A}, 'new': {'obj': C}})
        return value


def update_namespace(func, namespace):
    def wrapper(*args, **kwargs):
        # Update the globals
        func.__globals__[namespace['old']['name']] = namespace['new']['obj']
        val = func(*args, **kwargs)
        # Restore it back to the actual value
        func.__globals__[namespace['old']['name']] = namespace['old']['obj']
        return val
    return wrapper


d = D()
d.func_a()  # This should print C.a
d.func_b()  # This should print C.b

Output:

C.a
C.b


来源:https://stackoverflow.com/questions/45673983/override-used-classes-in-parent-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!