简体   繁体   English

包装 python 超类的所有方法

[英]Wrap all methods of python superclass

Is there a way to wrap all methods of a superclass, if I can't change its code?如果我不能更改它的代码,有没有办法包装超类的所有方法?

As a minimal working example, consider this base class Base , which has many methods that return a new instance of itself, and the descendent class Child作为一个最小的工作示例,考虑这个基础 class Base ,它有许多返回自身新实例的方法,以及后代 class Child

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)

The issue here is that calling childinstance.newinst_addseven() returns an instance of Base , instead of Child .这里的问题是调用childinstance.newinst_addseven()返回Base的实例,而不是Child

Is there a way to wrap the Base class's methods to force a return value of the type Child ?有没有办法包装Base类的方法来强制返回Child类型的值?

With something like this wrapper:使用类似这样的包装器:

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

Many thanks!非常感谢!


PS: What I currently do, is look at Base 's source code and add the methods to Child directly, which is not very mainainable: PS:我目前做的是查看Base的源代码并直接将方法添加到Child ,这不是很容易维护:

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

One option is to use a metaclass:一种选择是使用元类:

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

It will automatically wrap all the Base s methods with your force_child decorator.它会自动用你的force_child装饰器包装所有Base的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM