我正在创建一个继承自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'
答案 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__方法并提供了示例代码。