首页 > 解决方案 > How to call super().__init__(*args, **kwargs) with super() a specific instance

问题描述

Given this setup:

class Foo:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    def bar(self):
        return Bar(self.arg1, self.arg2)


class Bar(Foo):
    def __init__(self, arg1, arg2):
        super().__init__(arg1, arg2)


if __name__ == '__main__':
    foo = Foo(1, 2)
    print(foo.bar().arg1)
    print(foo.bar().arg2)

with Bar being a subclass of Foo is there a way to make Bar in bar() method in Foo recognize arg1 and arg2 of its superclass without passing them as parameters and without getting arg1 and arg2 out of __init__()?

标签: python-3.xoopinheritance

解决方案


解释

为了使BarinFoobar方法能够识别其父类的arg1arg2方法而不将它们作为参数传递,您可以将Foo对象的属性复制到Bar对象的属性。

这可以手动或自动完成,尽管自动化伴随着必须导入内置模块的成本inspect

解决方案

您可以手动执行此操作的方法是将Bar' 对象的属性设置为等于Foo对象的属性。由于Bar该类继承自Foo该类,因此您还需要覆盖以下__init__方法Bar

class Foo:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    def bar(self):
        temp_bar = Bar()
        temp_bar.arg1 = self.arg1
        temp_bar.arg2 = self.arg2
        return bar


class Bar(Foo):
    # Overrides the __init__ method
    def __init__():
        pass


if __name__ == '__main__':
    foo = Foo(1, 2)
    print(foo.bar().arg1)
    print(foo.bar().arg2)

第二种自动方式是将Foo对象的自定义创建的属性复制到Bar对象的属性中。这里inspect需要内置模块来获取Foo对象的属性,而我们可以只更新's 对象的__dict__属性Bar来复制属性:

import inspect

class Foo:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    def bar(self):
        temp_bar = Bar()
        # Creates a dummy object
        dummy = dir(type('Dummy', (object,), {}))

        # Iterates through all Foo object's attributes
        for item in inspect.getmembers(self):
            # Since the dummy object only has built-in attributes,
            # only custom-created ones will be used (in this case arg1 and arg2)
            if item[0] not in dummy:
                # Copies each attribute to temp_bar
                setattr(temp_bar, *item)

        return temp_bar


class Bar(Foo):
    # Overrides the __init__ method
    def __init__(self):
        pass


if __name__ == '__main__':
    foo = Foo(1, 2)
    print(foo.bar().arg1)
    print(foo.bar().arg2)

推荐阅读