【发布时间】:2020-07-13 14:00:01
【问题描述】:
我想要实现的是将类的特定方法调用与其子类的方法包装起来。我可以一个一个地做,像这样:
class Subclass(ParentClass):
def _handle_response(self, data, _suppress=None):
# process data
return data
def foo(self, *a, _suppress=None, **kw):
return self._handle_response(super().foo(*a, **kw), _suppress=_suppress)
def bar(self, *a, _suppress=None, **kw):
return self._handle_response(super().bar(*a, **kw), _suppress=_suppress)
但是由于有大约 20 种方法需要以这种方式包装,因此我觉得它非常多余。
我想出的另一种方法是像这样使用__getattribute__:
class Subclass(ParentClass):
def _handle_response(self, data, _suppress=None):
# process data
return data
def __getattribute__(self, attr):
if attr in {"foo", "bar"}:
def wrapped(_self, *a, _suppress=None, **kw):
return self._handle_response(
getattr(ParentClass, attr)(_self, *a, **kw),
_suppress=_suppress
)
return wrapped
return super().__getattribute__(attr)
这可行,但我对每次像这样调用方法时都会创建一个新的包装函数这一事实并不满意。这是我想避免的很多不必要的开销。我可以缓存这些,但同样,这似乎不是一个非常优雅的解决方案。
有人知道如何解决这个问题吗?
【问题讨论】:
-
这其中的开销在哪里?我假设这是网络调用的一部分。所以在任何时候,只有一个方法会被包装在一个新创建的函数中。 cmiiw.
-
如果我对
__getattribute__的工作方式没有完全误解,在这个例子中,每次调用foo都会创建一个新的wrapper函数。我通过将wrappers_created类变量添加到Subclass并在返回包装器之前将以下行添加到__getattribute__来测试它:Subclass.wrappers_created += 1。两次调用foo后,计数器位于2。 -
@leoOrion:这不适用于这里,因为在创建函数时会调用装饰器一次。您链接的问题是包装器创建了多少开销。我在说的是创建包装器的开销。 Afaik 装饰器不会在对装饰函数的每个函数调用上创建新的包装器。
-
我添加这个是为了暗示装饰器的想法。
标签: python