自动生成传递给子对象函数

问题描述 投票:0回答:1

我想在python中自动将函数调用转发给子类,以便父类具有所述函数,然后将调用转发给子类并将结果返回给调用者。像这样的东西:

class child:
    def __init__(self):
        self.b = 1

    def dosomething(self, a=1):
        print("child dosomething", a, self.b)
        return 'returning stuff'

class parent:
    def __init__(self):
        self.child = child()

    # I could do this for every func in child:
    def dosomething(self, *args, **kwargs):
        return self.child.dosomething()

p = parent()
p.dosomething()

因为我不想冒打字错误或忘记更新父级的风险,所以这应该自动完成,而不是像上面所示的那样,特别是如果子级有很多功能的话。

我可以通过为父类实现 getattr 来完成类似的事情,但是这样我的 IDE 和解释器都不知道父类/子类中的方法,这不是我想要的。

我探索的另一种方法是让孩子使用所有方法

def get_methods(x):
    return [
        [method, getattr(x, method)]
        for method in dir(x)
        if callable(getattr(x, method))
        if not method.startswith("_")
    ]

然后以某种方式将它们附加到我的父类中。 我可以使用

setattr(parent,'dosomething',func_from_get_methods(child))
来做到这一点 然后像以前一样调用它,但这行不通,因为父级没有 self.b.

那么,有没有Pythonic的方法可以做到这一点?

附注我不是在谈论子类化。

python function class parent-child
1个回答
0
投票

如果有人遇到这个“问题”...... 经过一些睡眠和一些修补后,我想出了一个解决方案。

原则上,这个想法是双重的:

  1. 通过对 Child 进行子类化,我可以在自动完成功能中获得所有功能
  2. add_pass_through_functions 然后用传递替换这些函数,以便parent.dosomething 被重定向到parent.child

我的代码:

def get_methods(x):
    # returns all methods of class x (or multiple classes)
    res = {}
    xs = x if isinstance(x, list) else [x]
    for x in xs:
        for method in dir(x):
            try:
                if callable(getattr(x, method)) and not method.startswith("_"):
                    res[method] = getattr(x, method)
            except:
                print(f'Skipping {method} due to error')
    return res


def add_pass_through_functions(parent_class, child_classes: list, child_variable_name: str):
    # adds all methods of the child_class(es) to the variable child_variable_name which belongs to parent_class
    methods = get_methods(child_classes)
    for name, method in methods.items():
        def wrap(func, doc):
            def f(self, *args, **kwargs):
                return getattr(getattr(self, child_variable_name), func)(*args, **kwargs)

            f.__doc__ = doc
            return f

        func = wrap(name, method.__doc__)
        setattr(parent_class, name, func)


class Child:
    def __init__(self):
        self.a = 1

    def dosomething(self, a=1):
        print("child dosomething", a)
        return 'returning stuff'


class Parent(Child): # by subclassing Child I get all methods in the autocomplete
    def __init__(self):
        self.child = Child()


add_pass_through_functions(parent_class=Parent, child_classes=Child, child_variable_name='child')

parent = Parent()
parent.dosomething()
© www.soinside.com 2019 - 2024. All rights reserved.