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

2024-09-28 03:21:05 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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  

构造函数的调用顺序如下: DFTAnalysisResultSaverSignalBase

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

但如果我改变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.__init__()直接调用构造函数 而且Common.Signal.__init__()than信号构造函数被调用了两次,所以对BaseAS的调用会调用信号构造函数,即使它不是它的父构造函数

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

那么BaseAS如何调用Signal构造函数呢


Tags: selfbase参数signalleninitdefcommon
2条回答

在您的示例中,AnalysisResultSaver.__init__中的超级调用是调用Signal.__init__的。这可能是违反直觉的,因为Signal不是AnalysisResultSaver的超类,并且是Python中多重继承和super函数工作的有趣方式的一个示例

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

如果按预期在AnalysisResultSaver中打印self.__class__,您将看到对象本身是DFT的实例。如果查看该类上的方法解析顺序self.__class__.__mro__或仅仅DFT.__mro__,您将看到一个类列表:DFTBaseASAnalysisResultSaverSignalBaseobject

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

如果您感兴趣,我建议您详细阅读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'>
================================================================================

此外,这是每个类别的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'>]

相关问题 更多 >

    热门问题