You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子类重写get_obj后,父类方法如何调用自身的get_obj?

问题:子类调用方法时,强制父类方法使用自身实现

类结构代码

from abc import ABC, abstractmethod

class grandparent(ABC):
    @abstractmethod
    def get_obj(self):
        pass

class ParentBase(grandparent):
    def __init__(self, obj1):
        self.obj1 = obj1

    def get_obj(self,func):
        return getattr(self.obj1, func)

    def get_base_obj(self):
        return super().get_obj('base') 
  
        
class child1(ParentBase):
    def __init__(self, obj1):
        super().__init__(obj1)

    def get_obj(self):
         return super().get_base_obj().getChild1()
        

class child2(ParentBase):
    def __init__(self, obj1):
        super().__init__(obj1)

    def get_obj(self):
        return super().get_base_obj().getChild2()

测试代码

child_instance = child1(obj1)
child_instance.get_obj()

错误情况

运行测试代码会抛出**“传入2个参数但预期1个”**的错误:

  • 原因:ParentBase.get_base_obj中调用super().get_obj('base')时,实际调用的是祖父类grandparent的抽象方法(该方法定义无参数),而非ParentBase自身的get_obj方法。
  • 若修改get_base_obj为以下形式,会调用子类重写的get_obj(无参数),同样报错:
    def get_base_obj(self, func_name):
        return self.get_obj(func)
    

需求

希望子类调用get_obj时,父类ParentBase的get_base_obj方法能调用父类自身的get_obj实现,而非子类或祖父类的版本。ParentBase是基类,不会被实例化,询问是否必须改为类方法或有无更优雅的实现。

临时解决方案(用户自实现)

修改ParentBase为以下形式可运行,但不够优雅:

class ParentBase(grandparent):
    def __init__(self, obj1):
        self.obj1 = obj1

    def get_obj(self,func):
        return self.obj1

    def get_base_obj(self):
        return ParentBase.get_obj(self, 'base') 

优雅实现方案

无需改为类方法,直接通过父类名调用实例方法的方式,显式指定调用ParentBase自身的get_obj,逻辑清晰且符合Python规范:

from abc import ABC, abstractmethod

class grandparent(ABC):
    @abstractmethod
    def get_obj(self):
        pass

class ParentBase(grandparent):
    def __init__(self, obj1):
        self.obj1 = obj1

    def get_obj(self, func):
        return getattr(self.obj1, func)

    def get_base_obj(self):
        # 显式调用父类自身的get_obj,绕过子类重写和祖父类抽象方法
        return ParentBase.get_obj(self, 'base') 
  
class child1(ParentBase):
    def get_obj(self):
         return super().get_base_obj().getChild1()

class child2(ParentBase):
    def get_obj(self):
        return super().get_base_obj().getChild2()

原理说明

在Python中,实例方法的第一个参数self是调用方法的实例对象。用ParentBase.get_obj(self, 'base')调用时,直接触发父类的方法实现,并将当前实例传入self,完全绕过子类的方法重写逻辑,也不会调用祖父类的抽象方法。

额外规范建议

祖父类grandparent的抽象方法get_obj无参数,但ParentBase的get_obj定义了参数,违反了抽象方法的契约(子类重写方法的签名应与抽象方法一致)。可调整祖父类定义,让参数更明确:

class grandparent(ABC):
    @abstractmethod
    def get_obj(self, func=None):
        pass

这样所有子类和父类的get_obj方法签名都符合抽象方法要求,代码更规范。


内容的提问来源于stack exchange,提问作者Rezzy138

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 06:43:16