覆盖父类中使用过的类 [英] Override used classes in parent class

查看:87
本文介绍了覆盖父类中使用过的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设在我无法编辑的地方有一个使用其他类LesserClass的类NiceClass

# NiceClass.py

class LesserClass:
    ...
    # stuff
    ...

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

现在,我想在继承的NiceClass

版本中的所有地方使用我自己的类MyLesserClass而不是LesserClass

# 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
    ...

但是MyNiceClass中所有不可重写的方法都将使用旧版NiceClass.py中的LesserClass.

如果我只是将NiceClass的整个定义复制粘贴到MyNiceClass.py,一切都会按我的意愿进行.

这就像我只想继承源代码,而不是整个命名空间一样.也许继承是错误的方式?

解决方案

我希望这仅限于使用LesserClass类的NiceClass下的方法.

现在,如果您希望MyNiceClass中的方法使用MyLesserClass而不是LesserClass,则可以更新这些方法的__globals__格,并将名称'LesserClass'指向MyLesserClass.

这是一个简单的示例,它通过覆盖 __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

输出:

C.a
C.b

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?

解决方案

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

这篇关于覆盖父类中使用过的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆