在孩子之前调用的父类

时间:2015-03-30 14:45:11

标签: python python-2.7 cython

我正在创建一个继承自PySndfile的子类,它包含与PySndfile类相关的额外函数。

但是,当使用不适用于PySndfile类的关键字参数初始化子类时,看起来参数会直接发送到父类,完全绕过子项的 init (即没有调用打印参数,参数不会从kwargs中弹出,并且追溯根本不会引用子类。

非常感谢任何帮助。

ClassProblem.py:

from pysndfile import PySndfile

class AudioFile(PySndfile):
    def __init__(self, filename, mode, rms="123"):
        print 'AudioFile init called'
        self.rms = rms
        super(AudioFile, self).__cinit__(
                self, 
                filename, 
                mode=mode, 
                format=None,
                channels=None, 
                samplerate=None
                )

aa = AudioFile(
    "/path/to/audio/file.wav",
    'r',
    rms="456",
    )

产生错误:

Traceback (most recent call last):
  File "ClassProblem.py", line 18, in <module>
    rms="456",
  File "_pysndfile.pyx", line 564, in _pysndfile.PySndfile.__cinit__ (_pysndfile.cpp:3308)
TypeError: __cinit__() got an unexpected keyword argument 'rms'

4 个答案:

答案 0 :(得分:1)

根据cython documentation,您似乎必须覆盖__new__

  

如果您希望在Python中继承您的扩展类型,您可能会发现提供 cinit ()方法*和**参数以便它可以接受并忽略额外参数很有用。否则,任何具有不同签名的 init ()的Python子类都必须覆盖 new ()[1]以及 init (),Python类的编写者不希望这样做。

答案 1 :(得分:0)

PySndfile似乎是一个Cython库。我对Cython一无所知,但从追溯中可以看出它使用__cinit__而不是__init__。您应该改为覆盖该方法。

答案 2 :(得分:0)

您实际上是将**kwargs传递给PySndfile构造函数,但它不知道如何处理特定于您的类的rms参数。我没有本地的PySndfile,但经过网上快速查看后,我发现pyx构造函数看起来像这样:

def __cinit__(self, filename, mode='r', int format=0,
             int channels=0, int samplerate=0):

这不是*args, **kwargs函数,能够接受任何参数,而是具有固定的签名。我建议使用类似的构造函数更新您的类,您可以在其中添加特定于您的类的参数:

def __init__(self, filename, mode='r', rms=0, format=0,
             channels=0, samplerate=0):

然后将所有参数传递给超级构造函数(除了rms,它不理解)。

答案 3 :(得分:0)

我通过将此问题发布到/r/learnpython sub-reddit

找到了答案

用户yes_or_gnome提供了一个很好的解释,说明为什么我需要覆盖__new__类方法以及__init__方法并提供了示例代码。