3

いくつかの型を変更する再利用可能なクラスにいくつかのコードがあります。ここに簡略化されたバージョンがあります。

class Foo:
    def __init__(self):
        self.count = 0

    def increment(self):
        self.count += 1

# Add another method outside of the class definition.
# Pylint doesn't care about this, and rates this file 10/10.

Foo.__dict__["current_count"] = lambda self: self.count

実際のコードでは、「current_count」は固定文字列ではなく変数であるため、次のように記述しませんでした。

Foo.current_count = lambda self: self.count # Cannot do in my scenario.

今、私のクライアントが新しい関数を使用するようになると、Pylint は恐怖で飛び跳ねます。

import server_api

def main():
    foo_count = server_api.Foo()
    foo_count.increment()


    print foo_count.current_count()
    # Pylint complains here:
    #     E1101:  8:main: Instance of 'Foo' has no 'current_count' member
    # I don't want to have to tell pylint to disable that message in every client.

main()

この新しい関数を使用するすべてのクラスは懲らしめられ、すべての参照でメッセージを無効にする必要があります。このクラスに不明な参照がある場合に、Pylint にチルするように指示するコードを API に追加したいと思います。

悲しいかな、pylint のドキュメントは...うーん...私の理解に資する品質ではなく、そこに提案を見つけることができませんでした。

要約すると、クライアントが参照するたびに、このクラスに関連する E1101 ルールをオフにするように API コードで pylint に指示できますか? 別の解決策はありますか?

4

3 に答える 3

6

Yoni H回答で提供され ているActiveStateクックブックレシピの例に触発された私のソリューションを次に示します。

Foo クラスに、この役に立たない__getattr__メソッドを追加しました。

def __getattr__(self, name):
    # This is only called when the normal mechanism fails, so in practice should never be called.
    # It is only provided to satisfy pylint that it is okay not to raise E1101 errors in the client code.
    raise AttributeError("%r instance has no attribute %r" % (self, name))

これは、以前のバージョンとほとんど区別がつかないはずです。通常のイベントの過程では呼び出されるべきではありませんが、このエラーについて黙っているように pylint を説得するには十分です。

ps このコードはあまりきれいではないと不平を言うことは許されます。私はその意見を共有します。しかし、クライアントにとっての利点は、コードの匂いよりも重要だと思います。

于 2010-08-18T18:13:45.183 に答える
2

コメントの1つに続いて、列挙型を使用するので、このSOの質問またはこのActiveStateクックブックのレシピを見てみませんか?

個人的な好みから、 SO質問の回答の1つと同じように、列挙型をクラスに追加することを選択します(コンテキストのために恥知らずにコピーされます):

class Animal:
   def __init__(self, name):
       self.name = name

   def __str__(self):
       return self.name

   def __repr__(self):
       return "<Animal: %s>" % self

Animal.DOG = Animal("dog")
Animal.CAT = Animal("cat")
于 2010-08-18T08:12:52.483 に答える
0

実用的に言えば、なぜ pylint (または任意の lint) が沈黙するべきであるという前提があるのでしょうか? 偽陽性と偽陰性の間には偏りがあるため、lint は前者を優先する必要があります。Pylint はその結果をスコアとして表現するため、人々はスコアを最大化する必要があると考えているように思えますが、「勝利」に対する賞はありません。

一方、それが不平を言っている構造は確かに醜いです。server_api が便宜上簡略化されていることは理解していますが、モジュールの名前空間をいじる必要は本当にありますか? あなたのクライアント コードから、current_countメソッド名がハード コードされているように見えますが、なぜサーバーにはありませんか?

于 2010-08-18T07:11:41.603 に答える