Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从包含或不包含**KWARG的类继承_Python_Class_Inheritance_Keyword Argument - Fatal编程技术网

Python 从包含或不包含**KWARG的类继承

Python 从包含或不包含**KWARG的类继承,python,class,inheritance,keyword-argument,Python,Class,Inheritance,Keyword Argument,我正在用Python构建一个plotting类,并希望完成以下工作。我想要一个使用PyQt5的图形窗口,它也继承了我创建的一些自定义类(例如曲线拟合类)。为了使曲线拟合类能够处理plotting类中存在的数据,它必须具有对plotting类中包含的数据的引用。因此,我选择了plotting类从CurveFitting类继承 问题似乎出现在继承PyQt5的GraphicsWindow类和我的自定义类时,它们接受不同数量的参数。我已经读到Python不能很好地处理使用“super”功能继承不同数量参

我正在用Python构建一个plotting类,并希望完成以下工作。我想要一个使用PyQt5的图形窗口,它也继承了我创建的一些自定义类(例如曲线拟合类)。为了使曲线拟合类能够处理plotting类中存在的数据,它必须具有对plotting类中包含的数据的引用。因此,我选择了plotting类从CurveFitting类继承

问题似乎出现在继承PyQt5的GraphicsWindow类和我的自定义类时,它们接受不同数量的参数。我已经读到Python不能很好地处理使用“super”功能继承不同数量参数的类,因此我决定让我的自定义CurveFitting类接受**kwargs,这将给它一个对父类的引用。然而,我随后遇到了另一个我不理解的错误。下面是我正在尝试做的一个整理好的例子

import numpy as np
from pyqtgraph import GraphicsWindow

class ClassA():
    def __init__(self, **kwargs):
        super().__init__()
        self.kwargs = kwargs
        self.parent = self.kwargs['parent']
        self.xdata = self.parent.xdata

    def print_data(self):
        print(self.parent.xdata)
        print(self.parent.ydata)


class classC(GraphicsWindow, ClassA):
    def __init__(self):
        kwargs = {}
        kwargs['parent'] = self
        kargs = kwargs
        self.xdata = np.linspace(0, 100, 101)
        self.ydata = np.linspace(0, 200, 101)

        super().__init__(**kwargs)
        # ClassA.__init__(self, **kwargs)
        # GraphicsWindow.__init__(self)

instC = classC()
instC.print_data()
当我运行上面的代码时,我在“super()。uu init(**kwargs)”行上得到了“RuntimeError:classC类型的super classinit()从未被调用”,我真的一点也不懂,并且已经尝试过谷歌搜索了一段时间,但没有结果

此外,我还尝试注释掉这一行,并取消注释接下来的两行以手动从每个类继承,但这也不起作用。我觉得很奇怪的是,如果我把这两行中的一行注释掉,它们都是单独工作的,但在一起却不工作。例如,如果我用两行运行它,它会给我一个错误,kwargs没有关键字“parent”,好像它甚至没有通过**kwargs


有没有一种方法可以从采用不同数量的初始化参数的两个类中继承?我有没有完全不同的方法来解决这个问题?谢谢

代码的直接问题是
ClassC
继承自
GraphicsWindow
作为第一个基类,而
ClassA
是第二个基类。当您调用
super
时,只调用一个(
GraphicsWindow
),如果它不是设计用于多重继承的(似乎是这样),它可能不会调用
super
本身,也可能不会传递
ClassA
所期望的参数

只要切换基类的顺序就足以使它工作。Python保证基类的调用顺序与它们在中的
class
语句中出现的顺序相同(不过如果以后发生更多继承,则可以在MRO中在它们之间插入其他类)。既然
ClassA.\uuuu init\uuuu
确实调用了
super
,它应该工作得更好

但是,要使
\uuuu init\uuuu
方法与多重继承一起工作可能很棘手,即使所有涉及的类都设计为与多重继承一起工作。这就是为什么经常避免使用位置参数,因为它们的顺序可能会变得非常混乱(因为子类只能在其父类的位置参数之前添加位置参数,除非它们想重复所有名称)。使用关键字参数绝对是一种更好的方法

但是您的代码使得处理关键字参数比它应该的要复杂一些。您不需要显式地创建字典来传递
**kwargs
语法,也不需要从使用
**kwargs
参数接受的dict中提取关键字值。通常每个函数都应该命名它所使用的参数,并且只对未知参数使用
**kwargs
(MRO中的其他类可能需要)。下面是它的样子:

class Base1:
    def __init__(self, *, arg1, arg2, arg3, **kwargs):  # the * means the other args are kw-only
        super().__init__(**kwargs)                      # always pass on all unknown arguments
        ...                                             # use the named args here (not kwargs)

class Base2:
    def __init__(self, *, arg4, arg5, arg6, **kwargs):
        super().__init__(**kwargs)
        ...

class Derived(Base1, Base2):
    def __init__(self, *, arg2, arg7, **kwargs):         # child can accept args used by parents
        super().__init__(arg2=arg2+1, arg6=3, **kwargs)  # it can then modify or create from
        ...                                              # scratch args to pass to its parents

obj = Derived(arg1=1, arg2=2, arg3=3, arg4=4, arg5=5, arg7=7) # note, we've skipped arg6
                                                              # and Base1 will get 3 for arg2

但我也会认真考虑,在你的情况下,继承是否有意义。将两个基类中的一个封装在子类中可能更有意义,而不是从子类继承。也就是说,您将只从
ClassA
GraphicsWindow
中的一个继承,并在
ClassC
的每个实例中存储另一个实例。(您甚至可以从两个基类中都不继承,并将它们都封装起来。)封装通常比继承更容易推理和正确处理。

关于代码的一些注释(因为它已经被简化了,我很欣赏):在
ClassA
super()的目的是什么?
c类
中的
kargs=kwargs
的目的是什么?您是否尝试过在
classC
中交换基类的顺序(以防
GraphicsWindow
处理varargs做得很好)?另外,可能值得回顾一下(我误解了您的代码,现在您使用
ClassA
a几乎是一个混音,这应该可以回答第一个问题)。谢谢,我认为我在这里学到的最好的东西是,当你不必依赖继承时,不必依赖继承。通过在plotting类中创建GraphicsWindow的实例,我能够实现相同的功能,然后绕过了所有其他问题。我可以通过切换GraphicsWindow和我的自定义类的顺序来运行这个类,但是进一步的复杂情况开始发生,我不理解。