包装python超类的所有方法

2024-06-26 13:48:27 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我不能更改超类的代码,有没有办法包装它的所有方法

作为一个最小的工作示例,考虑这个基类^ {< CD1>},它有许多方法返回自身的新实例,以及派生类^ {CD2>}/P>

class Base:
    
    def __init__(self, val):
        self.val = val
        
    def newinst_addseven(self):
        return Base(self.val + 7)
    
    def newinst_timestwo(self):
        return Base(self.val * 2)
    
    # ...

class Child(Base):
    
    @property
    def sqrt(self):
        return math.sqrt(self.val)

这里的问题是调用childinstance.newinst_addseven()返回Base的实例,而不是Child

是否有办法包装Base类的方法以强制返回类型为Child的值?

使用类似于此包装的东西:

def force_child_i(result):
    """Turn Base instance into Child instance."""
    if type(result) is Base:
        return Child(result.val)
    return result

def force_child_f(fun):
    """Turn from Base- to Child-instance-returning function."""
    def wrapper(*args, **kwargs):
        result = fun(*args, **kwargs)
        return force_child_i(result)
    return wrapper

非常感谢


PS:我现在做的是查看Base的源代码,并将方法直接添加到Child,这不是很容易维护的:

Child.newinst_addseven = force_child_f(Base.newinst_addseven)
Child.newinst_timestwo = force_child_f(Base.newinst_timestwo)

Tags: 方法instanceselfchildbasereturndefval
1条回答
网友
1楼 · 发布于 2024-06-26 13:48:27

一种选择是使用元类:

class ChildMeta(type):
    def __new__(cls, name, bases, dct):
        child = super().__new__(cls, name, bases, dct)
        for base in bases:
            for field_name, field in base.__dict__.items():
                if callable(field):
                    setattr(child, field_name, force_child(field))
        return child


class Child(Base, metaclass=ChildMeta):
    pass

它将自动使用force_child装饰程序包装所有Base的方法

相关问题 更多 >