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

如何在Python中自动将未实现的方法委托给其他类?

问题:如何在抽象基类中自动将未实现的方法转发给其他类实例

我有一个实现了x()和y()的类A,还有一个实现了z()的类B。现在有一个基类AbstractA,需要检测A上所有未实现的方法调用(比如z())并转发给B的实例。注意因为框架限制,A不能继承自B。示例代码如下:

from abc import ABC, abstractmethod   

class AbstractA(ABC):
   # 需要在这里实现捕获未实现方法并转发给B的逻辑,可访问B的实例(比如context.b)
   
   @abstractmethod
   def x():
     pass

   @abstractmethod
   def y():
     pass

class A(AbstractA):
  def __init__(self):
    super().__init__()

  def x():
    print('running x()')

  def y():
    print('running y()')

class B:
  def __init__(some plumbing args):
     super().__init__(some plumbing args) 

  def z():
     print('running z()')
 
a = A()
a.x()
a.y()
a.z()

需求背景

这个场景来自分层架构:数据访问层(DAL)是一组DAO类,封装所有数据库操作;服务应用层(SAL)基于DAL构建,整合数据与业务逻辑。比如PersonService调用PersonDao实现业务API,但客户端有时会请求直接调用DAO中的方法(比如find_by_id),希望在服务类的抽象基类层面自动完成方法透传,不用为每个DAO方法写重复的转发代码,让服务类成为DAO的外观层。

解决方案

核心是利用Python的__getattr__魔法方法——它会在访问对象不存在的属性(包括方法)时被触发。我们可以在AbstractA中实现这个方法,将未找到的方法转发给B的实例。

实现步骤

  1. 让AbstractA持有B的实例引用:可以通过全局上下文获取,或者在初始化时传入(推荐后者,更灵活)。
  2. 实现__getattr__方法:当调用A中未实现的方法时,从B的实例中获取对应方法并返回。

完整代码示例(基于上下文获取B实例)

from abc import ABC, abstractmethod

# 模拟上下文,提供B的实例
class Context:
    def __init__(self):
        self.b = B()

context = Context()

class AbstractA(ABC):
    def __getattr__(self, name):
        # 捕获未实现的方法,转发给B的实例
        return getattr(context.b, name)

    @abstractmethod
    def x(self):
        pass

    @abstractmethod
    def y(self):
        pass

class A(AbstractA):
    def x(self):
        print('running x()')

    def y(self):
        print('running y()')

class B:
    def __init__(self):
        pass

    def z(self):
        print('running z()')

# 测试
a = A()
a.x()  # 输出: running x()
a.y()  # 输出: running y()
a.z()  # 输出: running z()

更灵活的实现(初始化时传入B实例)

如果不想依赖全局上下文,可以通过初始化参数传递B实例:

from abc import ABC, abstractmethod

class AbstractA(ABC):
    def __init__(self, b_instance):
        self.b = b_instance

    def __getattr__(self, name):
        return getattr(self.b, name)

    @abstractmethod
    def x(self):
        pass

    @abstractmethod
    def y(self):
        pass

class A(AbstractA):
    def __init__(self, b_instance):
        super().__init__(b_instance)

    def x(self):
        print('running x()')

    def y(self):
        print('running y()')

class B:
    def __init__(self):
        pass

    def z(self):
        print('running z()')

# 测试
b = B()
a = A(b)
a.x()
a.y()
a.z()

注意事项

  • __getattr__只会在访问不存在的属性时触发,如果A中已经实现了某个方法(比如x()),不会被转发,符合需求。
  • 确保B实例在AbstractA中可正常访问,避免出现属性不存在的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 21:44:53