什么';Python中最简单的转发类定义是什么?

什么';Python中最简单的转发类定义是什么?,python,Python,我想在Python中实现一个转发类,实现一些基类,它在构造函数中接受同一基类的另一个实现,并为基类中的每个方法转发到该类 这对于提供定制点、为某些方法添加缓存、记录每个调用站点等都很有用 手动编写很简单。考虑到这个基类: class BaseClass(object): def method_a(self, *args): pass @property def prop_b(self): pass def method_c(se

我想在Python中实现一个转发类,实现一些基类,它在构造函数中接受同一基类的另一个实现,并为基类中的每个方法转发到该类

这对于提供定制点、为某些方法添加缓存、记录每个调用站点等都很有用

手动编写很简单。考虑到这个基类:

class BaseClass(object):
    def method_a(self, *args):
        pass

    @property
    def prop_b(self):
        pass

    def method_c(self, a, b, **kwargs):
        pass
下面是一个简单的转发实现

class ForwardBaseClass(BaseClass):
    def __init__(self, underlying_implementation):
        self._impl = underlying_implementation

    def method_a(self, *args):
        return self._impl.method_a(*args)

    @property
    def prop_b(self):
        return self._impl.prop_b

    def method_c(self, a, b, **kwargs):
        return self._impl.method_c(a, b, **kwargs)
只编写代码的缺点是有很多样板代码,必须为每个方法编写这些代码。当方法被添加到基类中时,类似的代码必须被添加到转发类中;如果需要更改类的转发方式,则必须通过所有方法进行更改。(例如,假设我们想要更改该类,以便它在每次调用时使用上下文管理器。)

有没有一种简短的Pythonic方法可以做到这一点,可以使用基本语言、内置模块,也可以使用PyPI上的某个可靠模块

所需功能:

  • 精确方法签名
    • 转发的签名应与基类匹配
    • 每个签名上都没有
      *args、**kwargs
  • 具有
    @property
    装饰符的方法已正确包装
  • \uuuuuuuuuu
    方法(如果存在)已正确包装
  • 在直接实现中,每个方法调用没有额外的成本
  • dir(instance)
    执行与直接实现相同的操作
很高兴有:

  • 基类不符合某些必要条件的错误消息
  • 有意义的文档字符串
  • 从结果对象派生的能力
  • 带有
    @staticmethod
    装饰器的方法被转发到传入实现的类
  • 带有
    @classmethod
    装饰符的方法被转发到传入实现的类
  • \uuuu init\uuuuuu
    \uuuu new\uuuuuuuu
    不转发
可能存在额外复杂性的地方:

  • 基类有一个元类
  • 基类有自己的多个基类
  • 一些更深奥的
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
我真的不在乎:

  • 多基类
  • 除了
    @property
    @staticmethod
    @classmethod
  • 转发类创建后对基类的修改

我只是想澄清一下我的评论:我的意思是+/-这(尽管需要更多的工作……而且:可能无法满足您的所有要求):


请注意,由于以下原因,您将无法以这种方式访问以
\uuuuuu
开头的成员。

您可以使用
getattr
将所有内容转发到
\uuuu init\uuuuuuu
\uu new\uuuuuuuuuuuuuuuuuuuuu>(以及其他您不希望的内容)中。这可能没有你想要的所有属性…坦白地说,我怀疑有没有一个简短的、python式的或者其他的方法来做到这一点!尤其是“在直接实现中,每个方法调用没有额外的成本”似乎很难满足,至少如果您想抓住所有奇怪的情况。例如,您建议的解决方案将调用重定向到
self.\u impl
对象-此额外调用会为每个调用带来一些额外成本。另外,要求
dir(instance)
工作意味着更多的工作可能会影响每次调用的成本。这对大多数
\uuuuuuuuu特殊的\uuuuuuuuuu
方法不起作用,因为这些方法是在插槽中查找的,永远不会通过
\uuuuuuuuuu getattr\uuuuuuu
进行。您可能还想实现
\uuuu dir\uuuu
来列出包装对象的属性。我同意(并且已经提到了您的一点)。但只要OP没有任何反应,我就不会进一步提出这个想法……我认为我之前的评论比我预期的更严厉。一般来说,你展示的方法是最好的,提问者的标准相当愚蠢。不用担心!你的评论绝对正确,切中要害,绝不严厉或冒犯。
class BaseClass(object):
    def method_a(self, *args):
        pass

    @property
    def prop_b(self):
        pass

    def method_c(self, a, b, **kwargs):
        pass

class ForwardBaseClass(BaseClass):
    def __init__(self, underlying_implementation):
        self._impl = underlying_implementation

    def __getattr__(self, name):
        # here you may have to exclude thigs; i.e. forward them to
        # self.name instead for self._impl.name
        try:
            return getattr(self._impl, name)
        except AttributeError:
            # do something else...

bc = BaseClass()
fbc = ForwardBaseClass(bc)
print(fbc.prop_b)
print(fbc.method_c(1,2,c=5))
print(dir(fbc))