Pylintの「パブリックメソッドが少なすぎます」というメッセージの意味


110

一部のコードでPylintを実行しているときに、「パブリックメソッドが少なすぎます(0/2)」というエラーを受け取ります。このメッセージはどういう意味ですか?pylintドキュメントは有用ではありません。

クラスのパブリックメソッドが少なすぎる場合に使用されるので、それだけの価値があることを確認してください。


1
あなたのクラスはどのように見えますか?クラスはデータの保存以外に何をしますか?
Blender 2012

1
クラスが行うのは、データを格納することだけです。
monsur

2
さて、あなたの問題があります。クラスはデータを格納するためのものではありません。それが辞書やリストのようなデータ構造のためのものです。
Blender 2012

興味深い、ありがとう!pylintのエラーメッセージがさらに役立つ可能性があります。とにかく、あなたのコメントを答えに変えてください、そして私は承認します。
monsur

6
しかし、「少数」の定義はどこにあるのでしょうか。方法は1つだけです。それがクラスが存在する理由です。pylintは「少数」をどのように定義しますか?2以上?どうして?
Zordid、

回答:


124

エラーは基本的に、クラスを辞書として扱うため、クラスはデータを格納するだけのものではないことを示しています。クラスには、保持するデータを操作するための少なくともいくつかのメソッドが必要です。

クラスが次のようになっている場合:

class MyClass(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

辞書またはnamedtuple代わりの使用を検討してください。クラスが最適だと思われる場合は、それを使用してください。pylintは常に何が最良かを認識しているわけではありません。

namedtupleは不変であり、インスタンス化時に割り当てられた値は後で変更できないことに注意してください。


72
「pylintは何が最適かわからない」ための+1-独自の判断を使用しますが、原則として、必要なものが「構造体」である場合は、dictまたはを使用しnamedtupleます。オブジェクトにロジックを追加する場合は、クラスを使用します(たとえば、オブジェクトの作成時に何かを実行したい場合、追加時に特別な処理を実行する必要がある場合、オブジェクトに対していくつかの操作を実行したい場合、その方法を制御したい場合)表示されるなど)
Burhan Khalid

詳しい回答ありがとうございます!私の使用例は、Burhanが述べたものと似ています。データが作成されたときに、データに対して何らかの処理を行っています。
monsur

6
クラス定義内にメタ(メタクラス)がある場合、このエラーは意味がありません。
alexander_ch

11
namedtuple吸う-醜い構文を持っている上に、それを文書化したり、デフォルト値を簡単に提供したりすることはできません。
rr-

6
使うたびにnamedtuple決断を後悔しました。名前付きアクセスとインデックス付きアクセスの両方の属性を許可することは一貫していません。
理論16

39

クラスを拡張している場合、私の提案は、この警告を体系的に無効にして、次に進むことです(たとえば、Celeryタスクの場合)。

class MyTask(celery.Task):  # pylint: disable=too-few-public-methods                                                                                   
    """base for My Celery tasks with common behaviors; extends celery.Task

    ...             

単一の関数のみを拡張する場合でも、このテクニックを機能させるにはクラスが必要です。拡張は、サードパーティのクラスをハックするよりも間違いなく優れています。


このdiableがあるため、コミット前は次のようになります。不良オプション値 'too-few-public-method'(bad-option-value)
Mercury

メソッドに「s」を含めましたか?bad-option-valueメッセージにはそれがありません。
セージ

4
おそらく、これを無効にするより良い方法を設定することであるmin-public-methods=0[BASIC]設定ファイルのセクション。これにより、disable=(内の[MESSAGE CONTROL])すべてのものとは別の行に配置できます。これにより、構成の変更とともに、有効化および無効化した理由に関する詳細なコメントを簡単に追加できます。
cjs 2018年

15

これは、pylintブラインドルールのもう1つのケースです。

「クラスはデータを格納するためのものではありません」-これは誤った説明です。辞書はすべてに適しているわけではありません。クラスのデータメンバーは意味があり、ディクショナリアイテムはオプションです。証明:dictionary.get('key', DEFAULT_VALUE)を防ぐために行うことができますが、デフォルトKeyErrorには単純なものはありません__getattr__

編集-構造体を使用するための推奨される方法

回答を更新する必要があります。現在-が必要な場合はstruct、2つの優れたオプションがあります。

a)使用するだけ attrs

これらはそのためのライブラリです:

https://www.attrs.org/en/stable/

import attr

@attr.s
class MyClass(object):  # or just MyClass: for Python 3
    foo = attr.ib()
    bar = attr.ib()

追加で得られるもの:コンストラクター、デフォルト値、検証__repr__、読み取り専用オブジェクト(namedtuplesPython 2でも置換する)を記述しないなど。

b)dataclasses(Py 3.7+ )を使用

hwjpのコメントに続いて、私もお勧めしdataclassesます:

https://docs.python.org/3/library/dataclasses.html

これはとほぼ同じattrsで、標準のライブラリメカニズム(「バッテリーを含む」)であり、Python 3.7以降を除いて、追加の依存関係はありません。

以前の回答の残り

NamedTuple特にpython 3の前ではよくありませんtyping.NamedTuplehttps : //docs.python.org/3/library/typing.html#typing.NamedTuple- 「から派生したクラスNamedTuple」パターンを確認する必要があります。Python 2- namedtuples文字列の説明から作成された-は醜く、悪く、「文字列リテラル内でのプログラミング」は愚かです。

私は現在の2つの回答(「他のものを使用することを検討してください。ただし、パイリントは常に正しいとは限りません」)に同意します。

もう一度指摘しておきます。一部のクラスは、データを格納することのみを目的しています。

考慮すべきオプションproperty--iesを使用します。

class MyClass(object):
    def __init__(self, foo, bar):
        self._foo = foo
        self._bar = bar

    @property
    def foo(self):
        return self._foo

    @property
    def bar(self):
        return self._bar

上記には読み取り専用のプロパティがあり、値オブジェクト(たとえば、ドメインドリブンデザインのプロパティ)では問題ありませんが、セッターを提供することもできます-このようにして、クラスは、所有するフィールドに対して責任を持つことができます-たとえばいくつかの検証などを行うには(セッターがある場合はself.foo = foo、directの代わりに、コンストラクターでそれらを使用して割り当てることができますがself._foo = foo、セッターは他のフィールドがすでに初期化されていると想定している可能性があり、コンストラクターでカスタム検証が必要です) 。


2
Python 3.7以降では、データクラスは名前付きタプルの醜さに対処する優れたソリューションを提供し、DDD値オブジェクトに最適です。
hwjp

私は同意し、2020年以降はそれが標準的な方法です。幅広いバージョン範囲のメカニズム(覚えているなら2.7、3.3以降)を使用するには、attrsライブラリを使用できdataclassesます。これは、実際にはモジュールを作成するための青写真でした。
Tomasz Gandor

namedtuples継承のための奇妙な構文があります... 1つを使用するすべてのクラスに、それが名前付きタプルであることを認識し、の__new__代わりに使用することを要求します__init__dataclassesこの制限はありません
Erik Aronesty

4

上司が単一の責任原則を期待するのは難しいですが、ピリントはそうではないと言います。したがって、クラスに2番目のメソッドを追加して、クラスが単一責任の原則に違反するようにします。あなたが単一の責任の原則をとるつもりであることがどれほど意図されているかは、見る人の目にあります。

私の修正、

クラスにメソッドを追加したので、2つの処理を実行します。

def __str__(self):
    return self.__class__.__name__

クラスを2つの別々のファイルに分割する必要があるのか​​と思っています。モジュールも同様です。

問題は解決しましたが、仕様の問題を解決するのではなく、終日仕様を議論している同僚と一緒ではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.