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

Python类中无冗余代码/docstring的方法属性转发重定向最优方案

解决方案

1. 自动实现方法调用转发

方案一:使用__getattr__魔法方法(最简实现)

Python 中对象的属性/方法查找优先级里,__getattr__会在类本身没有对应属性时触发,刚好可以用来做自动转发:

class Foo:
    def __init__(self, bar: Bar):
        self.bar = bar

    def __getattr__(self, method_name):
        # 所有Foo类未定义的方法,都会转发给self.bar的对应方法
        return getattr(self.bar, method_name)

如果需要限制可转发的方法范围,避免暴露内部方法,可加白名单控制:

class Foo:
    # 允许对外暴露的Bar类方法列表
    _ALLOWED_FORWARD_METHODS = {"name", "run", "get_config"}
    def __init__(self, bar: Bar):
        self.bar = bar

    def __getattr__(self, method_name):
        if method_name in self._ALLOWED_FORWARD_METHODS:
            return getattr(self.bar, method_name)
        raise AttributeError(f"'Foo' object has no attribute '{method_name}'")

注意:该方案运行时调用完全正常,但IDE的类型提示、docstring预览可能不生效,对开发体验有要求可以看第二种方案。

方案二:动态批量绑定方法(支持类型提示+docstring同步)

如果需要兼容IDE提示,可以在类定义完成后批量生成转发方法,不需要手动逐个定义:

from functools import wraps

class Foo:
    _FORWARD_TO_BAR = {"name", "run", "get_config"}
    def __init__(self, bar: Bar):
        self.bar = bar

# 批量生成转发方法
for method_name in Foo._FORWARD_TO_BAR:
    original_func = getattr(Bar, method_name)
    @wraps(original_func)
    def wrapper(self, *args, __method_name=method_name, **kwargs):
        return getattr(self.bar, __method_name)(*args, **kwargs)
    setattr(Foo, method_name, wrapper)

2. 自动同步docstring

上面方案二已经天然解决了docstring同步的问题:functools.wraps装饰器会自动把原方法的__doc__、__name__、注解等元信息全部复制到转发方法上,不需要做任何额外操作,运行时调用help(Foo.name)、IDE预览docstring都可以正常显示Bar类对应方法的文档内容。

如果只需要同步少量方法,也可以用装饰器手动标记,不需要批量生成:

from functools import wraps

def forward(attr_name: str):
    def decorator(func):
        # 从目标类的方法中复制元信息
        original_func = getattr(Bar, func.__name__)
        @wraps(original_func)
        def wrapper(self, *args, **kwargs):
            return getattr(getattr(self, attr_name), func.__name__)(*args, **kwargs)
        return wrapper
    return decorator

class Foo:
    def __init__(self, bar: Bar):
        self.bar = bar
    
    @forward("bar")
    def name(self): ...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 02:27:04