15

そのため、外部アカウント プロバイダー (Twitter、Facebook など) に接続するためのモジュールを作成しています。それ自体では役に立たないスーパークラスがありますが、認証トークンを永続化するためにサブクラスによって呼び出される必要がある汎用メソッドが含まれています。認証トークンとプロバイダーの認証解除。私の質問は、それをインスタンス化できないようにする方法はありますか、それとも同意した大人のルールに従い、それを使用する人が適切と思われるように間違いを犯すようにするべきですか? docstring 以外に、誰かがこのスーパークラスを単独で使用してはならないことを示す良い方法はありますか?

4

4 に答える 4

7

私はSven Marnach の編集を支持します。「同意する大人」の規則に従い、クラスがインスタンス化されることを意図していないことを docstring で言及する必要があると思います。

あなたの質問のキー フレーズは、「それ自体では役に立たないスーパークラスがあります」です。インスタンス化されたときに cthulhu を呼び出すことはありません。プログラムの他の場所で、壊滅的でデバッグが困難な障害が発生することはありません。それはほんのわずかな時間の無駄です。それはクラスを不自由にする価値がないと思います。

于 2011-06-06T19:42:41.030 に答える
7

JABの答えに基づいて、次の__new__()ように書く方が便利かもしれません:

class NoInstantiation(object):
    def __new__(cls, *args, **kwargs):
        if cls is NoInstantiation:
            raise RuntimeError(
                "NoInstantiation isn't meant to be instantiated")
        else:
            return super(NoInstantiation, cls).__new__(cls, *args, **kwargs)

__new__()そうすれば、派生クラスで上書きする必要はありません。

編集:JABの回答の改善としてこの回答を投稿しましたが、上記のコードを実際に使用しないことをお勧めします。それはどういうわけか意図的にあなたのクラスを不自由にしています。通常の Python の方法は、クラスがインスタンス化されることを意図していないことを明確に文書化することです。しかし、いずれにせよ誰かがこれがどのように役立つかを発見するかもしれません。人々があなたのライブラリをどのように使用するかは決してわかりません。

于 2011-06-06T19:07:42.317 に答える
7
class NoInstantiation:    # "class NoInstantiation(object):" in Python 2.2+ or whatever
    def __new__(cls):
        "This class is not meant to be instantiated, so __new__ returns None."
        return None

これは、必要に応じてその機能をオーバーライドすることを止めるものではありませんが、偶発的なインスタンス化を防ぐためのかなり適切な方法である必要があります。誰かが誤って電話をかけたとしても、あなたが警告しなかったとは言えません。

編集: 本当に親切にしたい場合は、stderr に警告を出力し__new__()たり、例外をスローしたりすることもできます。

編集 2: 例外ルートに行く場合は__init__()、代わりにスーパークラスのメソッド内で例外を発生させることをお勧めします。これは、ユーザーが__init__()サブクラスでオーバーライドする可能性が高いためです。

編集 3: 設定__new__または__init__等しいオプションもありますNoneが、結果のエラーはあまり有益ではありません。

于 2011-06-06T18:51:19.407 に答える
4

abstractmethodモジュールでデコレータを使用してabc、すべての派生クラスがオーバーライドするメソッドの 1 つを抽象としてマークすることができます。

In [1]: import abc

In [2]: class C:
   ...:     __metaclass__ = abc.ABCMeta
   ...:     
   ...:     @abc.abstractmethod
   ...:     def my_abstract_method(self, *args) :
   ...:         pass
   ...:     
   ...:     

In [3]: c = C()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/afoglia/<ipython console> in <module>()

TypeError: Can't instantiate abstract class C with abstract methods my_abstract_method

しかし、私はクラス編成に疑問を持っています。この「スーパークラス」がサブクラスによって呼び出される必要がある関数にすぎない場合、なぜそれは別のメカニズムが使用できる単なるモジュールではないのでしょうか? 派生クラスが (おそらくテンプレート メソッド パターンとして) 完全に実装するインターフェイスの定義である場合、抽象メソッドは、派生クラスによって実装を与える必要がある関数を表します。その場合、ベースを構築不可能にすることさえ気にせず、ファクトリ メソッドを通じて必要な派生物を人々に取得させるか、失敗した関数を呼び出したときにユーザーにそれを理解させます。(ただし、ドキュメント文字列にコメントを入れてください。)

于 2011-06-06T19:49:53.683 に答える