20

私は、言語に「開発者を保護する」機能が組み込まれている C# のバックグラウンドを持っています。私は、Python が「ここではすべて大人」のアプローチを取り、開発者に思慮深く慎重にコーディングする責任を負わせていることを理解しています。

そうは言っても、Python は、プライベート インスタンス変数の先頭にアンダースコアなどの規則を提案しています。私の質問は、クラスをdocstringで指定する以外に、クラスを抽象としてマークするための特定の規則はありますか? 抽象クラスの命名規則について言及しているPythonスタイルガイドには特に何も見たことがありません。

これまでのところ3つのオプションを考えることができますが、それらが良いアイデアかどうかはわかりません:

  1. クラスの上の docstring で指定します (見落とされる可能性があります)。
  2. クラス名の先頭にアンダースコアを使用します (これが普遍的に理解されているかどうかは不明です)
  3. エラーdef __init__(self):を発生させる抽象クラスでメソッドを作成します(基本コンストラクターを呼び出したい場合のように、これが継承に悪影響を与えるかどうかは不明です)

これらのいずれかが適切なオプションですか、それともより良いオプションがありますか? 他の開発者がそれが抽象的であることを知っていることを確認したいだけなので、インスタンス化しようとすると、奇妙な動作の責任を受け入れる必要があります。

4

6 に答える 6

24

Python 2.6 以降を使用している場合、抽象化を強制する場合は、標準ライブラリのAbstract Base Classモジュールを使用できます。次に例を示します。

from abc import ABCMeta, abstractmethod

class SomeAbstractClass(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def this_method_must_be_overridden(self):
        return "But it can have an implementation (callable via super)."

class ConcreteSubclass(SomeAbstractClass):
    def this_method_must_be_overridden(self):
        s = super(ConcreteSubclass, self).this_method_must_be_overridden()
        return s.replace("can", "does").replace(" (callable via super)", "")

出力:

>>> a = SomeAbstractClass()
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    a = SomeAbstractClass()
TypeError: Can't instantiate abstract class SomeAbstractClass with abstract
methods this_method_must_be_overridden
>>> c = ConcreteSubclass()
>>> c.this_method_must_be_overridden()
'But it does have an implementation.'
于 2013-02-20T06:49:15.803 に答える
5

あなたの最後の文に基づいて、「それを文書化するだけ」と答えます。ドキュメンテーションで禁止されている方法でクラスを使用する人は、異常な動作に対する責任を負わなければなりません。

Python には抽象基本クラスメカニズムがありますが、インスタンス化を思いとどまらせることが唯一の目的である場合は、それを使用する理由がわかりません。

于 2013-02-20T05:14:09.263 に答える
3

「抽象」クラスを作成raise NotImplementedError()し、抽象メソッドで作成します。

人々がクラスを使用するのを止めることはなく、真のダックタイピング方法で、抽象メソッドの実装を怠った場合に通知されます。

于 2013-02-20T06:03:52.967 に答える
3

抽象クラスに接頭辞「Abstract」を付けて名前を付けるだけです。例: AbstractDevice、AbstractPacket など。

それはそれが来るのと同じくらい簡単で要点です。他の人が先に進んで「抽象」という単語で始まるクラスをインスタンス化および/または使用することを選択した場合、彼らは自分が何をしているのかを知っているか、とにかく彼らに希望がありませんでした.

このように名前を付けることは、多くのクラスの前に「Abstract」を置くのもばかげているように感じるため、深い抽象化階層に夢中にならないように自分自身に思い出させるのにも役立ちます。

于 2013-02-20T06:25:18.987 に答える
0

物事を強制することは可能ですが、むしろ不自然です。私が何年にもわたって C++ プログラミングを行った後に Python にたどり着いたとき、私も同じことをしようとしました。メタクラスは仕事をしますが、いずれにせよ、Python はコンパイル時にほとんどチェックしません。チェックは引き続き実行時に実行されます。では、特定のクラスを作成できないことは、実行時にのみ発見された場合に本当に役立つのでしょうか? C++ (および C# も同様) では、抽象クラスを作成するコードをコンパイルすることさえできません。抽象メソッドがある場合は、NotImplementedError例外は十分にあるようです。注意: エラーコードを返さずに発生させます! Python のエラーは、明示的にサイレントにしない限り、通常はサイレントにすべきではありません。文書化。抽象的であると言う方法でクラスに名前を付けます。それで全部です。

Python コードの品質は、ほとんどの場合、高度なコンパイル時の型チェックを備えた言語で使用されるメソッドとはまったく異なるメソッドによって保証されています。個人的には、動的に型付けされたゲージと他のゲージとの最も重大な違いだと思います。単体テスト、カバレッジ分析など。その結果、コードの設計はまったく異なります。すべては強制ではなく、できるだけ簡単にテストできるようにするために行われます。

于 2013-02-20T07:01:52.390 に答える