使用 mixin 时返回 base class 的签名

Returning signature of base class when using a mixin

我有一个 class B 由多重继承定义。

class A:
    def __init__(self, x, y):
      self.x = x
      self.y = y

class AMixin:
    def __init__(self, *args, **kwargs):
      # do stuff
      super().__init__(*args, **kwargs)

class B(AMixin, A):
    pass

基本上 mixin class 覆盖了 __init__ 方法,但是从使用 class B, class [=13] 的用户的角度来看=]的签名与A相同。

由于我在 mixin class 中使用 *args**kwargs,因此 B 的初始化是基于 A 的构造函数(功能上)。

然而,linters 不会知道这一点,他们会认为 B 的签名是 argskwargs,这有点没用。

我认为这与检查 B 时让 inspect.signature return A 的签名(而不是 AMixin)的问题相同,但是现在这是我检查 B 时得到的结果:

from inspect import signature
signature(B).parameters.keys()
# odict_keys(['args', 'kwargs'])

如何做到 return ['x', 'y']

ClassB__init__继承自AMixinclass。尽管 AMixin 使用 **args**kwargs 调用 super(),但它的 __init__ 函数可以执行您想要的任何逻辑。 linter 扩展函数内部的内容 运行 没有意义。

所以经过一些研究,在 this post 的帮助下,我想出了一个解决方案,将 class B 装饰成这样:

from functools import wraps

def BaseSignature(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    # Override signature
    wrapper.__signature__ = signature(f.__mro__[2])
    return wrapper

那么B定义为:

@BaseSignature
class B(AMixin, A):
    pass

现在 signature(B) 给出 <Signature (x, y)>,而且 linter 也运行良好。

虽然它有效,但对我来说仍然不理想,因为我有几十个,并且不希望为所有这些添加相同的装饰器。