Я полностью осознаю, что pylint
и другие инструменты статического анализа не являются всезнающими, и иногда их советам нужно не подчиняться. (Это относится к различным классам сообщений, а не только к convention
.)
Если у меня есть классы, такие как
class related_methods():
def a_method(self):
self.stack.function(self.my_var)
class more_methods():
def b_method(self):
self.otherfunc()
class implement_methods(related_methods, more_methods):
def __init__(self):
self.stack = some()
self.my_var = other()
def otherfunc(self):
self.a_method()
Очевидно, что это надумано. Вот лучший пример, если хотите .
Я считаю, что этот стиль называется использованием "mixins".
Как и другие инструменты, pylint
оценивает этот код -21.67 / 10
, в первую очередь потому, что он думает, more_methods
а related_methods
не имеет self
или имеет атрибуты otherfunc
, stack
и my_var
потому , что без запуска кода он, очевидно, не может видеть related_methods
и more_methods
смешиваться с ним implement_methods
.
Компиляторы и инструменты статического анализа не всегда могут решить проблему остановки , но я чувствую, что это, безусловно, тот случай, когда рассмотрение того, что унаследовано, implement_methods
показало бы, что это совершенно правильно, и это было бы очень легко сделать.
Почему инструменты статического анализа отклоняют этот допустимый (я думаю) шаблон ООП?
Или:
Они даже не пытаются проверить наследство или
миксин не рекомендуется в идиоматическом, читаемом Python
№ 1, очевидно, неверно, потому что, если я попрошу pylint
рассказать мне о моем классе, который наследует, unittest.TestCase
который использует self.assertEqual
(что-то определено только в unittest.TestCase
), он не будет жаловаться.
Миксины не пифоничны или не одобряются?
Ответы:
Mixins просто не тот случай использования, который рассматривался инструментом. Это не означает, что это обязательно плохой вариант использования, просто необычный для Python.
Правильно ли используются миксины в конкретном случае - это другой вопрос. Мишиновый анти-паттерн, который я вижу чаще всего, использует миксины, когда предполагается, что это только одна комбинация. Это просто окольный способ скрыть класс бога. Если вы не можете думать о причине прямо сейчас , чтобы поменять или оставить одну из Mixins, она не должна быть Mixin.
источник
Я считаю, что Миксинс, безусловно, может быть Pythonic. Тем не менее, идиоматический способ заставить замолчать ваш линтер - и улучшить читаемость вашего Mixins - это как (1) определять абстрактные методы, которые явно определяют методы, которые должны реализовывать потомки Mixin, так и (2) предварительно определять
None
поля для элементов данных Mixin, которые должны инициализировать дочерние элементы.Применение этого шаблона к вашему примеру:
источник
abstract other(self): pass
вещьЯ думаю, что миксин может быть хорошим, но я также думаю, что Pylint является правильным в этом случае. Отказ от ответственности: основанные на мнении вещи следуют.
Хороший класс, включая миксин, несет одну четкую ответственность. В идеале миксин должен нести все состояние, к которому он собирается получить доступ, и логику для его обработки. Например, хороший миксин может добавить
last_updated
поле в класс модели ORM, предоставить логику для его установки и методы для поиска самой старой / самой новой записи.Ссылка на необъявленные члены экземпляра (переменные и методы) выглядит немного странно.
Правильный подход во многом зависит от поставленной задачи.
Это может быть миксин с соответствующим битом состояния, хранящимся в нем.
Это может быть другая иерархия классов, где методы, которые вы в настоящее время распространяете через миксин, находятся в базовом классе, в то время как различия реализации более низкого уровня принадлежат подклассам. Это выглядит наиболее подходящим для вашего случая со стековыми операциями.
Это может быть декоратор класса, который добавляет метод или два; обычно это имеет смысл, когда нужно передать некоторые аргументы декоратору, чтобы повлиять на генерацию метода.
Изложите свою проблему, объясните свои большие проблемы с дизайном, и мы могли бы поспорить, если в вашем случае что-то противоречит шаблону.
источник
Линтер не знает, что вы используете класс как миксин. Pylint знает, что вы используете миксин, если вы добавляете суффикс «миксин» или «миксин» в конце имени класса, тогда линтер перестает жаловаться.
Миксины сами по себе не плохие или хорошие, просто инструмент. Вы делаете их хорошим или плохим использованием.
источник
Все ли в порядке с миксином?
Миксины не приветствуются - они являются хорошим вариантом для множественного наследования.
Почему ваш линтер жалуется?
Pylint явно жалуется , потому что он не знает , где
otherfunc
,stack
иmy_var
откуда.Trivial?
Нет очевидной веской причины для того, чтобы разделить эти два метода на отдельные родительские классы, как в вашем примере в вопросе, так и в вашем более тривиальном связанном примере, показанном здесь.
Затраты на миксины и шум
Затраты на то, что вы делаете, заставляют ваш постинтер сообщать о шуме. Этот шум может скрыть более важные проблемы с вашим кодом. Это важная стоимость для взвешивания. Другой ценой является то, что вы разделяете свой взаимосвязанный код на разные пространства имен, что может затруднить программистам понимание значения.
Вывод
Наследование позволяет повторно использовать код. Если вы получаете повторное использование кода со своими миксинами, прекрасно, они создали ценность для вас, которая, вероятно, перевешивает возможные другие затраты. Если вы не получаете повторное использование кода / дедупликацию строк кода, вы, вероятно, не получаете большую пользу для своих миксинов, и в этот момент я думаю, что стоимость шума выше, чем выгода.
источник