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