Чи поєднує Python суміш проти схеми?


34

Я цілком усвідомлюю, що pylintта інші інструменти статичного аналізу не є всезнаючими, і іноді їхні поради повинні бути не дотримані. (Це стосується різних класів повідомлень, а не лише conventions.)


Якщо у мене є заняття на кшталт

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()

Очевидно, це надумано. Ось кращий приклад, якщо вам подобається .

Я вважаю, що цей стиль називають використанням "міксинів".

Як і інші інструменти, pylintставки цей код в -21.67 / 10першу чергу тому , що він думає , more_methodsі related_methodsне мають selfабо атрибути otherfunc, stack, annd my_varбо без виконання коду, він , очевидно , не може бачити related_methodsі more_methodsзмішують в до implement_methods.

Компілятори та інструменти статичного аналізу не завжди можуть вирішити проблему зупинки , але я вважаю, що це, безумовно, випадок, коли дивлячись на те, що успадковано, implement_methodsбуло б показано, що це абсолютно вірно, і це було б дуже легко зробити.

Чому інструменти статичного аналізу відкидають цю дійсну (я думаю) схему OOP?

Або:

  1. Вони навіть не намагаються перевірити спадщину чи

  2. міксини відбиваються від ідіоматичного, читаного Python


№1, очевидно, неправильно, тому що якщо я попрошу pylintсказати мені про мій клас, який успадковує, unittest.TestCaseякий використовує self.assertEqual, (щось визначене лише в unittest.TestCase), він не скаржиться.

Чи міксини непітонічні чи не відсторонені?


1
Це погане питання? Це поза темою? це невідчутно? Я дурний? Люди можуть DV, але вони не хочуть допомогти покращити його.
кіт

1
Деякі люди, які, ймовірно, втомилися від того, щоб люди запитували: "це" анти -) модель "чи" це (не) пітоніка ".

9
@MichaelT Це добре. Потім вони можуть перестати розглядати питання.
Katana314

2
@tac люди зголошуються з різних причин, але ніколи не вимагають говорити, чому - кнопка downvote має підказку, що говорить: "Це питання не показує жодних зусиль для дослідження; воно незрозуміле чи не корисне" - невиразний, якщо прийнятна відповідь. 8 вгору і 1 вниз насправді дуже непогані, особливо з питання, де попутні канали безкоштовні. Не дозволяйте це збити вас. Ура.
Аарон Хол

@AaronHall Я знаю, що людям дозволено робити те, що їм подобається, своїми голосами, адже я кажу новим користувачам, які скаржаться на те саме.
кіт

Відповіді:


16

Mixins просто не є випадком використання, який розглядався інструментом. Це не означає, що це обов'язково випадки поганого використання, просто рідкість для python.

Чи правильно застосовуються міксини в конкретному випадку, інша справа. Я думаю, що найчастіше я зустрічаю міксин, використовуючи міксини, коли коли-небудь передбачається поєднання однієї комбінації. Це просто круговий спосіб приховати клас богів. Якщо ви не можете думати про причини прямо зараз , щоб поміняти або залишити одну з Mixins, вона не повинна бути Mixin.


так, я визнаю, це об'єкт бога. У цьому випадку я можу стверджувати, що це нормально, щоб процесор був об'єктом бога.
кіт

15

Я вважаю, що Мікінс може бути абсолютно пітонічним. Однак ідіоматичний спосіб замовкнути літер - і покращити читабельність Вашого Мікінса - полягає в тому, щоб (1) визначити абстрактні методи, які чітко визначають методи, які повинні застосовувати діти Міксіна, і (2) попередньо визначити None-значні поля для членів даних Mixin, які діти повинні ініціалізувати.

Застосовуючи цей зразок до вашого прикладу:

from abc import ABC, abstractmethod


class related_methods():
    my_var = None
    stack = None

    def a_method(self):
        self.stack.function(self.my_var)


class more_methods(ABC):
    @abstractmethod
    def otherfunc(self):
        pass

    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()

2
+1 за вашу відповідь, хоча abstract other(self): passріч торгує плутаниною лайнера для моєї
кішка

Це ще більше заплутано без @ab абстрактmethod ;-) Я почав спочатку з Java, тому це для мене просто чудово.
Кріс Хуанг-Лівер

9

Я думаю, що міксини можуть бути хорошими, але я також вважаю, що в цьому випадку пілінт є правильним. Відмова від відповідальності.

Хороший клас, включаючи міксини, несе одну чітку відповідальність. В ідеалі, міксин повинен містити весь стан, до якого він збирається отримати доступ, і логіку для цього. Наприклад, хороший міксин може додати last_updatedполе до класу моделей ORM, надати логіку для його встановлення та методи пошуку найстарішого / найновішого запису.

Посилання на незадекларовані члени екземпляра (змінні та методи) виглядає дещо дивно.

Правильний підхід дуже залежить від завдання.

Це може бути міксин з відповідним бітом стану, що зберігається в ньому.

Це може бути інша ієрархія класів, коли методи, які ви зараз поширюєте за допомогою mixin, знаходяться в базовому класі, тоді як відмінності в реалізації нижчого рівня належать до підкласів. Це виглядає найбільш підходящим для вашого випадку з операціями стеку.

Це може бути декоратор класу, який додає метод або два; це, як правило, має сенс, коли вам доведеться передати декоративні аргументи, щоб вплинути на створення методу.

Заявіть про свою проблему, поясніть свої великі проблеми дизайну, тоді ми можемо стверджувати, чи щось у вашому випадку є антизією.


6

Лінійку не відомо, що ви використовуєте клас як міксин. Pylint знає, що ви використовуєте mixin, якщо додаєте суфікс 'mixin' або 'Mixin' в кінці назви класу, тоді лінійка перестає скаржитися.

linter_without_mixins linter2_with_mixin

Міксини не погані чи хороші самі по собі, є лише інструментом. Ви робите їх корисним або поганим.


2
це читається більше як коментар, див. Як відповісти
gnat

2
це цінна відповідь, тому що я не думаю, що я ніколи не знав би про цей натяк інакше
кіт

1

Міксини добре?

Чи поєднує Python суміш проти схеми?

Міксини не відлякують - вони є гарним випадком використання для багаторазового успадкування.

Чому ваш скарбник скаржиться?

Pylint явно скаржиться , тому що він не знає , де otherfunc, stackі my_var звідки.

Тривіальний?

Немає одразу очевидних вагомих причин розділити ці два методи на окремі батьківські класи, або у вашому прикладі у запитанні, або у вашому більш тривіальному зв'язаному прикладі, показаному тут.

201
202 class OpCore():
203     # nothing runs without these
204
205 class OpLogik(): 
206     # logic methods... 
207 
208 class OpString(): 
209     # string things
210 
211 
212 class Stack(OpCore, OpLogik, OpString): 
213 
214     "the mixin mixer of the above mixins" 

Витрати на міксин та шум

Витрати на те, що ви робите, викликають шум у звіті про літери. Цей шум може затьмарити більш важливі проблеми з вашим кодом. Це важлива вартість для зважування. Інша вартість полягає в тому, що ви розділяєте свій взаємопов'язаний код на різні простори імен, що може ускладнити програмістам розкриття сенсу.

Висновок

Спадкування дозволяє повторно використовувати код. Якщо ви отримаєте повторне використання коду за допомогою ваших комбінацій, чудово, вони створили для вас цінність, яка, ймовірно, перевершує можливі інші витрати. Якщо ви не отримуєте повторне використання / дедупликація коду рядків коду, ви, мабуть, не отримуєте великої цінності для своїх комбінацій, і в цей момент, я думаю, вартість шуму перевищує переваги.


Є вагома причина розділити їх у пов'язаному нетривіальному прикладі - мені простіше впорядкувати свій код, коли у мене є частка повного класу, який реалізує математику, інший, який реалізує рядки тощо, і ви змішуєте їх разом щоб отримати Форт Суп.
кіт

"Інша вартість полягає в тому, що ви розділяєте свій код на різні простори імен, що може ускладнити програмістам відкриття значення" - ні, це зовсім не так. Простіри імен класу полегшують розповісти, що робить група методів, і коли хтось хоче використовувати стек, він повинен зателефонувати / реалізувати Forth Soup, а не окремі інгредієнти
кішка

@cat, мабуть, тому, що вони надумані і не використовуються в реальному великому проекті, жоден приклад насправді не підтримує ваші моменти використання mixins. Обидва демонструють лише один раз, коли використовується міксин, і в цьому випадку кращий стиль та організація - просто поставити реалізацію на одне місце. Тепер, якщо ви могли б показати випадок, коли ви хочете використовувати загальні риси в усіх класах, але не хочете загального базового класу, саме тут ви б використовували міксин. Що поруч із вашим провідним питанням (UltraBird так добре відповів). Але це відповідає на ваше запитання, що стосується застосованості суміші.
dlamblin
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.