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.