Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.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中具有不同参数调用列表的构造函数_Python_Constructor_Initialization_Superclass_Diamond Problem - Fatal编程技术网

超类';Python中具有不同参数调用列表的构造函数

超类';Python中具有不同参数调用列表的构造函数,python,constructor,initialization,superclass,diamond-problem,Python,Constructor,Initialization,Superclass,Diamond Problem,我写了钻石继承类。如果在同一级别有两个类,那么构造函数的参数列表长度不同,并且取决于基声明列表中的声明顺序,所有操作正常或立即抛出错误 class DFT(Common.BaseAS, Common.Signal): def __init__(self, fs, N, history_len=1, strict=False): super().__init__(fs, N, history_len, strict, np.complex) class BaseAS

我写了钻石继承类。如果在同一级别有两个类,那么构造函数的参数列表长度不同,并且取决于基声明列表中的声明顺序,所有操作正常或立即抛出错误

class DFT(Common.BaseAS, Common.Signal):

    def __init__(self, fs, N, history_len=1, strict=False):

        super().__init__(fs, N, history_len, strict, np.complex)


class BaseAS(abc.ABC, AnalysisResultSaver):
   No constructor here

class AnalysisResultSaver(Base):

    def __init__(self, fs=8000, N=250, history_len=1, strict=False, dtype=None):

        super().__init__(fs, N, dtype)

class Signal(Base):

    def __init__(self, fs, N, dtype=None):
        super().__init__(fs, N, dtype)

class Base:

    def __init__(self, fs, N, dtype=None):
       Stuff  
构造函数的调用顺序如下:
DFT
AnalysisResultSaver
信号
Base

在这种情况下,一切正常,但我的问题是 1) 如何将参数传递给
Signal
constructor如果没有直接指示哪些参数是正确的,它只是被修剪到前两个吗

但如果我改变DFT中基的顺序,我得到

super().__init__(fs, N, history_len, strict, np.complex)
TypeError: __init__() takes from 3 to 4 positional arguments but 6 were given
我知道它改变了mro,但在第一种情况下,它工作得很好

如果我想通过
Common.BaseAS.\uuuu init\uuuuu()直接调用构造函数
Common.Signal.\uuu init\uuu()
比Signal构造函数被调用了两次,所以对BaseAS的调用会调用Signal构造函数,即使它不是它的父函数

Common.BaseAS.__init__(self, fs, N, history_len, strict, np.complex)
Common.Signal.__init__(self, fs, N)

因此,2)如何调用
BaseAS
信号
构造函数?

在您的示例中,
分析结果版本中的超级调用。\uuu init\uuu
就是调用
信号的。这可能是违反直觉的,因为
Signal
不是
AnalysisResultSaver
的超类,它是Python中多重继承和
super
函数工作的有趣方式的一个例子

特别是,当您在
AnalysisResultSaver
中编写
super()
时,这实际上是
super(AnalysisResultSaver,self)
的简写。那么这到底是做什么的呢?它查看您传入的实际实例(
self
)的方法解析顺序,并尝试查找传入的类(
AnalysisResultSaver
)之后的第一个匹配方法

如果按预期在
AnalysisResultSaver
中打印
self.\uuuuu class\uuuu
,您将看到对象本身是
DFT
的实例。如果您查看该类上的方法解析顺序
self.\uuu class.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

注意
AnalysisResultSaver
之后的第一个函数是
Signal
,这就是它决定
Signal的方式。\uuuu init\uuuu
是它接下来应该调用的特定构造函数


如果您感兴趣,我建议您详细阅读Python的多重继承和
super
函数;网上有许多资源更全面地介绍了这一主题。

由@KSab给出的答案是正确的,但我将添加这一点,因为它有助于说明正在发生的事情(并且是在该答案中提出的)。我对您的代码进行了一些修改,以准确地显示正在发生的事情以及这些对象的构造顺序。代码如下:

import abc
import numpy as np

class Base:
    def __init__(self, fs, N, dtype=None):
        print('='*80)
        print(f"Base fs: {fs}")
        print(f"Base N: {N}")
        print(f"Base dtype: {dtype}")


class Signal(Base):
    def __init__(self, fs, N, dtype=None):
        print('='*80)
        print(f"Signal self: {self}")
        print(f"Signal fs: {fs}")
        print(f"Signal N: {N}")
        print(f"Signal dtype: {dtype}")
        print("Signal(Base) will now call:  super().__init__(fs, N, dtype)")
        super().__init__(fs, N, dtype)


class AnalysisResultSaver(Base):
    def __init__(self, fs=8000, N=250, history_len=1, strict=False, dtype=None):
        print('='*80)
        print(f"ARS self: {self}")
        print(f"ARS fs:{fs} ")
        print(f"ARS N: {N}")
        print(f"ARS history_len: {history_len}")
        print(f"ARS strict: {strict}")
        print(f"ARS dtype: {dtype}")
        print("ARS(Base) will now call:  super().__init__(fs, N, dtype)")
        super().__init__(fs, N, dtype)

class BaseAS(abc.ABC, AnalysisResultSaver):
    pass

class DFT(BaseAS, Signal):
    def __init__(self, fs, N, history_len=1, strict=False):
        print('='*80)
        print(f"DFT self: {self}")
        print(f"DFT fs:{fs} ")
        print(f"DFT N: {N}")
        print(f"DFT history_len: {history_len}")
        print(f"DFT strict: {strict}")
        print("DFT(BaseAS, Signal) will now call: super().__init__(fs, N, history_len, strict, np.complex)")
        super().__init__(fs, N, history_len, strict, np.complex)



my_d = DFT('fs', 32, 10, True)
它将产生以下输出:

================================================================================
DFT self: <__main__.DFT object at 0x10cabe310>
DFT fs:fs
DFT N: 32
DFT history_len: 10
DFT strict: True
DFT(BaseAS, Signal) will now call: super().__init__(fs, N, history_len, strict, np.complex)
================================================================================
ARS self: <__main__.DFT object at 0x10cabe310>
ARS fs:fs
ARS N: 32
ARS history_len: 10
ARS strict: True
ARS dtype: <class 'complex'>
ARS(Base) will now call:  super().__init__(fs, N, dtype)
================================================================================
Signal self: <__main__.DFT object at 0x10cabe310>
Signal fs: fs
Signal N: 32
Signal dtype: <class 'complex'>
Signal(Base) will now call:  super().__init__(fs, N, dtype)
================================================================================
Base fs: fs
Base N: 32
Base dtype: <class 'complex'>
================================================================================
================================================================================
DFT自我:
DFT-fs:fs
干膜厚度N:32
DFT历史记录:10
DFT严格:真
DFT(BaseAS,Signal)现在将调用:super()。\uuuu init\uuuu(fs,N,history\u len,strict,np.complex)
================================================================================
ARS self:
财政司司长:财政司司长
北区:32
历史博物馆:10
真的吗
ARS数据类型:
ARS(Base)现在将调用:super()。\uuuu init\uuu(fs,N,dtype)
================================================================================
信号自我:
信号fs:fs
信号N:32
信号数据类型:
信号(基本)现在将调用:super()。\uuuu init\uuu(fs,N,dtype)
================================================================================
基本fs:fs
基数N:32
基本数据类型:
================================================================================
此外,这是每个类别的MRO:

>>> DFT.mro()
[<class '__main__.DFT'>, <class '__main__.BaseAS'>, <class 'abc.ABC'>, <class '__main__.AnalysisResultSaver'>, <class '__main__.Signal'>, <class '__main__.Base'>, <class 'object'>]
>>> BaseAS.mro()
[<class '__main__.BaseAS'>, <class 'abc.ABC'>, <class '__main__.AnalysisResultSaver'>, <class '__main__.Base'>, <class 'object'>]
>>> AnalysisResultSaver.mro()
[<class '__main__.AnalysisResultSaver'>, <class '__main__.Base'>, <class 'object'>]
>>> Signal.mro()
[<class '__main__.Signal'>, <class '__main__.Base'>, <class 'object'>]
>>> Base.mro()
[<class '__main__.Base'>, <class 'object'>]
>DFT.mro()
[, , , ]
>>>BaseAS.mro()
[, , ]
>>>AnalysisResultSaver.mro()
[, ]
>>>Signal.mro()
[, ]
>>>Base.mro()
[, ]

回答得好,我还添加了一个,其中包括一些运行代码,以帮助演示此处发生的情况。这种类继承结构让我头晕目眩。谢谢,它解释了构造函数是如何被称为hanks的。虽然我自己编写了一些带有print的代码,但正是您添加的参数让我了解了构造函数调用参数的来源。我看到“ARS”“super()”调用了“Signal”构造函数,并且由于它的参数设置与“Base”相同,因此与调用没有冲突