最近在做数据预处理时,因为要使用父类的一些功能,所以希望继承父类实现自己的数据预处理子类。具体的实现是:子类重写了父类的方法,在子类的方法中显示调用了父类的同名该方法,结果运行后发现子类的方法被调用了多次,造成了结果与实际不一样。经过查看父类的该同名方法发现,父类方法实现过程中进行了递归调用,所以,在父类方法中有递归调用时,且子类方法重写时调用了父类方法,则需要注意多次调用的问题。
简化版的代码如下
1 | class Base: |
父类的test
方法进行了递归调用,子类重写父类的test
方法,且在子类test
方法中调用了父类的方法。运行结果如下:
1 | 3 |
我们发现子类方法的print("ok")
被调用了多次,经过单步调试后发现,父类的test
方法在递归调用时,调用的是子类的test
方法,所以会出现这个bug。仔细一下,应该是此处的父类的self
引用已经指向了子类。因此,我们在父类test
方法中显示调用父类的test
方法,代码如下:
1 | class Base: |
运行后结果如我们预期:
1 | 3 |
所以,关于继承关系中self
引用的类已经改变了的猜想是对的。这个问题后续需要更加深入了解,self
的具体机制,还有在重写基类方法时,如果需要显示调用基类方法,则注意基类方法中是否含有递归调用。