Возвращение подписи базового класса при использовании миксина - PullRequest
0 голосов
/ 03 января 2019

У меня есть класс 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 переопределяет метод __init__, но с точки зрения пользователей, использующих класс B, подпись класса B такая же, как A.

Поскольку я использую *args и **kwargs в классе mixin, то инициализация B основана на конструкторе A (функционально).

Однако, линтеры этого не узнают, и они подумают, что подпись B - args и kwargs, что бесполезно.

Я думаю, что это та же проблема, что и inspect.signature возвращает подпись A (вместо AMixin) при проверке B, но теперь вот что я получаю, когда проверяю B:

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

Как заставить его вернуть ['x', 'y'] вместо этого?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Итак, после некоторого исследования и с помощью этого поста я придумал решение, украсив 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)>, и линтер также работает хорошо.

Хотя это работает, для меня это все еще не идеально, потому что у меня их десятки, и я не собираюсь добавлять один и тот же декоратор ко всем из них.

0 голосов
/ 04 января 2019

Класс B __init__ наследуется от AMixin класса.Даже если AMixin вызывает super() с **args и **kwargs, его функция __init__ может выполнять любую логику по вашему желанию.Для Линтера не имеет смысла расширять то, что выполняется внутри функции.

...