简体   繁体   中英

Returning signature of base class when using a mixin

I have a class B defined by multiple inheritance.

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

Basically the mixin class overrides the __init__ method, but from the point of view of users using class B , class B 's signature is same as A .

Since I am using *args and **kwargs in the mixin class, then B 's initialization is based on A 's constructor (functionally).

However, linters won't know that and they would think that B 's signature is args and kwargs , which is kind of unhelpful.

I think this is he same problem as letting inspect.signature return A 's signature (instead of AMixin ) when inspecting B , but now here is what I get when I inspect B :

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

How to make it return ['x', 'y'] instead?

Class B __init__ is inherited from AMixin class. Even though AMixin is calling super() with **args and **kwargs , its __init__ function can execute any logic as you want. It doesn't make sense for linter to expand on what's being run inside a function.

So after some research, and with the help of this post , I came up with a solution by decorating class B as such:

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

So then B is defined as:

@BaseSignature
class B(AMixin, A):
    pass

and now signature(B) gives <Signature (x, y)> , and the linter is also working nicely.

Although it works, it is still not ideal for me, because I have tens of those, and not looking forward to add the same decorator to all of them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM