pylint
と他の静的分析ツールがすべてを知っているわけではなく、時にはそれらのアドバイスに従わない必要があることを十分に認識しています。 (これは、convention
sだけでなく、さまざまなクラスのメッセージに適用されます。)
私のようなクラスがある場合
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
にself
または属性otherfunc
、stack
、anndがないと考えているため、このコードをrelated_methods
で評価しますmy_var
は、コードを実行しないと、related_methods
とmore_methods
がimplement_methods
に混在しているように見えないためです。
コンパイラーと静的分析ツールは常に停止問題を解決できるわけではありません ですが、これは確かにimplement_methods
によって継承されたものを見るとこれが完全に有効であることを示す場合であり、それは非常に重要です簡単なこと。
静的分析ツールがこの有効な(私は思う)OOPパターンを拒否するのはなぜですか?
どちらか:
彼らは継承をチェックする試行さえしません
慣用的で読みやすいPythonでは、ミックスインは推奨されません。
#1は明らかに正しくありません。_pylint
に、unittest.TestCase
を使用するself.assertEqual
を継承するクラス(unittest.TestCase
でのみ定義されているもの)を教えてもらった場合、文句を言う。
ミックスインは非Pythonicですか?
ミックスインは、ツールで検討された使用例ではありません。それは、それが必ずしも悪いユースケースであることを意味するのではなく、Pythonの珍しいものです。
ミックスインが特定のインスタンスで適切に使用されるかどうかは、別の問題です。私が最も頻繁に目にするミックスインのアンチパターンは、1つの組み合わせの混合のみが意図されている場合にのみ、ミックスインを使用しています。これは、神のクラスを隠すための迂回的な方法にすぎません。 今のところスワップアウトしたり、ミックスインの1つを除外したりする理由がわからない場合は、ミックスインであってはなりません。
Mixinsは、絶対にPythonicになることができると私は信じています。ただし、リンターを沈黙させ、Mixinsの可読性を向上させる慣用的な方法は、(1)define abstract methods で、Mixinの子が実装する必要があるメソッドを明示的に定義します。 (2)子が初期化する必要があるMixinデータメンバーのNone
値フィールドを事前定義します。
このパターンをあなたの例に適用する:
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()
私は思いますミックスインは良いことですが、この場合、パイリントも正しいと思います。免責事項:オピニオンベースのものが続きます。
良いクラスには、ミックスインが含まれ、明確な責任が1つあります。理想的には、ミックスインはアクセスするすべての状態と、それを処理するロジックを運ぶ必要があります。例えば。良いmixinはlast_updated
フィールドをORMモデルクラスに追加し、それを設定するためのロジックを提供し、最も古い/最新のレコードを検索するメソッドを提供します。
宣言されていないインスタンスメンバー(変数とメソッド)を参照すると、少し奇妙に見えます。
適切なアプローチは、手元のタスクに大きく依存します。
これは、関連する状態のビットが保持されているミックスインである可能性があります。
下位クラスの実装の違いがサブクラスに属している一方で、ミックスインを介して現在配布しているメソッドが基本クラスにある別のクラス階層である可能性があります。これは、スタック操作の場合に最も適しているように見えます。
メソッドを1つまたは2つ追加するクラスデコレータである場合があります。これは通常、メソッドの生成に影響を与えるためにいくつかの引数をデコレータに渡す必要がある場合に意味があります。
あなたの問題を述べ、あなたのより大きなデザインの懸念を説明してください、そしてあなたのケースで何かがアンチパターンであるかどうか私たちは議論することができます。
Python mixinsはアンチパターンですか?
ミックスインは推奨されていません-多重継承の良いユースケースです。
otherfunc
、stack
、およびmy_var
がどこから来ているのかがわからないため、Pylintは明らかに文句を言っています。
これらの2つのメソッドを別々の親クラスに分ける理由がすぐには明らかではありません。問題の例か、ここに示す簡単なリンクされた例のどちらかです。
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"
あなたがしていることのコストはあなたのリンターレポートを騒がしくしています。このノイズにより、コードのより重要な問題がわかりにくくなる場合があります。これは重要なコストです。もう1つのコストは、相互に関連するコードを異なる名前空間に分離しているため、プログラマーがその意味を見つけにくくなる可能性があることです。
継承により、コードの再利用が可能になります。あなたがあなたのミックスインでコードを再利用するなら、すばらしいことですが、おそらく他の可能なコストを上回る価値を生み出しています。コード行のコードの再利用/重複排除が得られない場合、ミックスインの価値はあまり得られないでしょう。その時点で、ノイズのコストはメリットよりも大きいと思います。