超类';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”相同,因此与调用没有冲突