【问题标题】:How to slightly modify an inherited attribute from parent __init__() with minimal changes in the child class in Python?python - 如何在Python中对子类进行最小更改的情况下稍微修改从父__init__()继承的属性?
【发布时间】:2020-08-22 02:00:19
【问题描述】:

代码如下:

def some_function1():
    pass

def some_function2():
    pass

def some_function3():
    pass

def some_function4():
    pass

class ReporterClass():
    def __init__(self, data_reporter):
        self.data_reporter = data_reporter

class ParentClass():
    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2
        self.datacollector = ReporterClass(data_reporter={
            'Report info 1': some_function1,
            'Report info 2': some_function2,
            'Report info 3': some_function3,
            })

class ChildClass(ParentClass):
    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2
        self.datacollector = ReporterClass(data_reporter={
            'Report info 1': some_function1,
            'Report info 2': some_function2,
            'Report info 3': some_function3,
            'Report info 4': some_function4,
            })

这在这个玩具示例中运行良好,但我在实际代码中遇到的问题是__init__() 中有很多参数,例如param1...param100。同样,data_reporter 中有很多字典项,例如,Report info 1 ... Report info 100。我喜欢通过将'Report info 4': some_function4 添加到ChildClass 中的self.datacollector 来简单地进行修改,而不必完全覆盖父级的__init__() 并且不必重复所有参数代码。任何提示或建议将不胜感激。

--- 编辑 ---

要详细解释。根据建议,我会将子类创建为ChildClass1。但是,我的类在初始化中有很多参数。我不仅需要将它们全部写在子班'__init__() 中,我还需要在super().__init__() 中“重复”它们。所以我想知道是否有更方便和优雅的方式不必重复自己。 ChildClass2 之类的东西?

class ChildClass1(ParentClass):
    def __init__(self, 
                        param1, 
                        param2,
                        ., # Very long list of parameters
                        .,
                        .,
                        param100,
    ):
        super().__init__(
                        param1, 
                        param2,
                        ., # Very long list of parameters
                        .,
                        .,
                        param100
                        )
        self.datacollector.data_reporter['Report info 4'] = some_function4

class ChildClass2(ParentClass):
    def __init__(self, *args):
        some_var_to_store_parent_init_params = super().__init__.attr

        for param in some_var_to_store_parent_init_params:
            # somehow assign it back to ChildClass' args

        super().__init__(some_var_to_store_parent_init_params)

        self.datacollector.data_reporter['Report info 4'] = some_function4

【问题讨论】:

    标签: python-3.x class oop inheritance initialization


    【解决方案1】:

    调用super()__init__()将帮助您很好地重用父__init__;那么你可以在ChildClass的'ReporterClass.datacollector'属性中添加必要的附加功能

    您可以进一步重构 ReporterClass.datacollector 的构建方式以使用参数填充它 - 在这里,在调用 super() 之后直接添加其他值。

    def some_function1(): pass    
    def some_function2(): pass
    def some_function3(): pass
    def some_function4(): pass
    
    
    class ReporterClass:
        def __init__(self, data_reporter):
            self.data_reporter = data_reporter
    
    
    class ParentClass:
        def __init__(self, param1, param2):
            self.param1 = param1
            self.param2 = param2
            self._data_reporter = {'Report info 1': some_function1,
                                   'Report info 2': some_function2,
                                   'Report info 3': some_function3}
            self.datacollector = ReporterClass(self._data_reporter)
    
    
    class ChildClass(ParentClass):
        def __init__(self, param1, param2):
            super().__init__(param1, param2)
            self.datacollector.data_reporter['Report info 4'] = some_function4
    
    
    if __name__ == '__main__':
    
        print(ParentClass(1, 2).datacollector.data_reporter)
        print(ChildClass(3, 4).datacollector.data_reporter)
    

    [编辑] -----------

    如果您发现处理许多参数很麻烦,您可以使用 args、kwargs,如下所示:

    class ParentClass:
        def __init__(self, *args):
            self.param1, self.param2 = args
            self._data_reporter = {'Report info 1': some_function1,
                                   'Report info 2': some_function2,
                                   'Report info 3': some_function3}
            self.datacollector = ReporterClass(self._data_reporter)
    
    
    class ChildClass(ParentClass):
        def __init__(self, *args):
            super().__init__(*args)
            self.datacollector.data_reporter['Report info 4'] = some_function4
    
    
    if __name__ == '__main__':
    
        print(ParentClass(1, 2).datacollector.data_reporter)
        print(ChildClass(3, 4).datacollector.data_reporter)
    

    【讨论】:

    • 谢谢。有没有办法 ChildClass 可以从父级的 __init__ 继承相同的 param#,因此 param1 和 param2 不需要在 ChildClass 的 __init__ 中显式写入/重复?
    • 不确定我是否理解您的问题。在上面发布的示例中,子类使用父类的属性,它们没有重复;参数被传递给super() 作为调用父级__init__ 的参数,在那里它们被分配给属性。这些属性是子类的,继承自父类。
    • 我在原帖中添加了一些修改,如果清楚请告诉我。我搜索了一段时间,但找不到任何我希望的例子,就像我在上面的理论化 ChildClass2 中一样。
    • 谢谢,这是一个非常接近我想要的解决方案。但是,我的问题是,__init__(self, *args) 是否必须同时在 ParentClass 和 ChildClass 中?我不介意在 ParentClass 中拼出所有启动参数。我实际上更喜欢它,这样我就可以写像ParentClass(param1=1, param2=2).datacollector.data_reporter 这样的东西,现在我不能接受你的最终建议。是不是真的没有办法在ParentClass中保留参数规范,而只在ChildClass中使用*args
    【解决方案2】:

    假设我正确理解您的问题,以下内容是否符合您的要求?

    class MaybeWorks:
        def __init__(self, num_funcs, *args):
            for k, arg in enumerate(args):
                setattr(self, 'param'+str(k+1), arg)
            data_reporter=dict()
            for k in range(num_funcs):
                data_reporter['Report info '+str(k+1)] = globals()['some_function'+str(k+1)]
            self.datacollector = ReporterClass(data_reporter)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-24
      • 1970-01-01
      • 2020-11-08
      • 1970-01-01
      • 2016-02-20
      • 1970-01-01
      • 1970-01-01
      • 2020-02-20
      相关资源
      最近更新 更多