Подавить предупреждение о неожиданном аргументе в миксине

Я пишу миксин в Python3.8:

class Cloneable:
    def change_field(self, **kwargs):
        """ Create a new object with only the specified properties changed."""
        argdict = {**kwargs, **{key: self.__getattribute__(key) for key in self.__slots__ if
                                key not in kwargs and key[:2] != '__'}}
        return self.__class__(**argdict) 

В PyCharm я получаю предупреждение «Неожиданный аргумент» в последней строке. Предположительно, это связано с распаковкой аргумента ключевого слова. Если бы это была функция, я мог бы включить **kwargs в сигнатуру функции, но это миксин, и я заранее не знаю, к какому __init__ он будет относиться.

Как я могу подавить такие надоедливые предупреждения?


person Daniel Moskovich    schedule 25.05.2020    source источник
comment
Я нашел этот вопрос, который кажется функционально идентичным. Может быть, этот вопрос следует закрыть как дубликат? stackoverflow.com/questions/59606289/   -  person Daniel Moskovich    schedule 26.05.2020


Ответы (2)


Проверить модуль

Расширьте свой миксин классами, которые его используют, и используйте проверить модуль.

С приведенной ниже настройкой мы:

  1. сохранить список всех имен аргументов из __init__ подкласса
  2. отфильтровать argdict по нашему списку

Мы подавляем предупреждения, не создавая их.

import inspect

class Mixin:
    @property
    def names(self):
        return self.__names

    def __init__(self):
        sig = inspect.signature(self.__init__)
        self.__names = list()
        for param in sig.parameters.values():             # Signature(a=None, b=None).values()
            self.__names.append(str(param).split('=')[0]) # str(Parameter(a=None)).split('=')[0]
        print(self.names)    # [a, b]

    def change_field(self, **kwargs):
        """ Create a new object with only the specified properties changed."""
        argdict = {**{key: self.__getattribute__(key) for key in self.__slots__}, **kwargs}
        return self.__class__(**{k:v for k, v in argdict.items() if k in self.names})


class App(Mixin):
    def __init__(self, a=None, b=None):
        Mixin.__init__(self)

App()

Более

Ты делал это задом наперёд. Вы должны позволить kwargs перезаписывать __slots__ ключей. Вы также пытаетесь подавить ключи, которые заканчиваются двойным подчеркиванием. Все, что не принадлежит (включая дандеры), будет удалено в этом финальном фильтре.

person Michael Guidry    schedule 25.05.2020
comment
Спасибо тебе за это! Пробовал, но предупреждение все равно есть. - person Daniel Moskovich; 25.05.2020
comment
А именно, self.__class__(**{k:v for k, v in argdict.items() if k in self.names}) по-прежнему выдает мне предупреждение Unexpected argument и в этом коде. - person Daniel Moskovich; 25.05.2020
comment
Я честно не знаю. Скопируйте окончательный фильтр в вызов печати и посмотрите, что в нем. Возможно, вы заметите закономерность. Уберите фильтр из вызова __class__ и введите одно очень простое и универсальное значение, которое никогда не должно вызывать ошибку... вы получили ошибку? если это так, возможно, пришло время напечатать self.__class__ и его тип. Этот звонок __class__ был проблемой все это время. - person Michael Guidry; 26.05.2020
comment
Когда вы говорите, что PyCharm предупреждает вас, вы имеете в виду редактор? Например, у вас есть маленькая оранжевая метка на полосе прокрутки? Если это так, наведите курсор на предупреждение, выберите «дополнительные действия», щелкните стрелку подменю для «игнорировать ...», выберите тип игнорирования, которое вы хотите выполнить. - person Michael Guidry; 26.05.2020
comment
Мне удалось решить эту проблему - спасибо за вашу помощь! Я опубликую свое решение как еще один ответ - пожалуйста, прокомментируйте, если у вас есть какие-либо мысли. - person Daniel Moskovich; 26.05.2020

Мне удалось решить проблему. Спасибо Майклу Гидри за его вклад в то, что порядок словарей должен быть обратным!

Решение состояло в том, чтобы включить в миксин фиктивный метод __init__, который принимает **kwargs в качестве аргумента:

class Cloneable:
    def __init__(self, **kwargs):
        ...

    def change_field(self, **kwargs):
        argdict = {key: self.__getattribute__(key) for key in self.__slots__}
        return self.__class__(**{**argdict, **kwargs})
person Daniel Moskovich    schedule 26.05.2020