Java の抽象クラスについては誰もがよく知っていますが、Python では abc モジュールを使用して抽象クラスを構築する方法を説明します
Java と同様に、Python でも抽象クラスを定義できます。
抽象クラスについて話す前に、抽象メソッドの実装について話しましょう。
抽象メソッドは、基本クラスで定義されているメソッドですが、実装はありません。 Javaではメソッドをインターフェースとして宣言できます。 Python で抽象メソッドを実装する簡単な方法は次のとおりです:
class Sheep(object): def get_size(self): raise NotImplementedError
Sheep から継承されたサブクラスはすべて get_size メソッドを実装する必要があります。そうしないとエラーが生成されます。しかし、この実装方法には欠点があります。定義されたサブクラスは、そのメソッドが呼び出されたときにのみエラーをスローします。クラスがインスタンス化された後にトリガーする簡単な方法を次に示します。 Python が提供する abc モジュールを使用します。
import abc class Sheep(object): __metaclass__ = abc.ABCMeta @abc.absractmethod def get_size(self): return
Sheep クラスまたはそこから継承されたサブクラスをインスタンス化するときに例外がスローされます (get_size は実装されていません)。
したがって、抽象クラスを定義することにより、サブクラスの共通メソッドを定義できます (実装を強制します)。
抽象クラスの使い方
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def load(self, input): return @abc.abstractmethod def save(self, output, data): return
ABCMetaメタクラスを通じて抽象クラスを作成し、抽象メソッドを示すためにabstractmethodデコレータを使用します
具体クラスを登録します
class B(object): def load(self, input): return input.read() def save(self, output, data): return output.write(data) A.register(B) if __name__ == '__main__': print issubclass(B, A) # print True print isinstance(B(), A) # print True
抽象クラスからを登録します具象クラス
サブクラス化の実装
class C(A): def load(self, input): return input.read() def save(self, output, data): return output.write(data) if __name__ == '__main__': print issubclass(C, A) # print True print isinstance(C(), A) # print True
これにより、抽象クラスを継承するメソッドを使用して具象クラスを実装できます。ただし、副作用として、すべての具象クラスが基本から見つけられるようになります。 class
for sc in A.__subclasses__(): print sc.__name__ # print C
継承を使用すると、すべての具象クラスが見つかります。 register を使用すると、具象クラスが存在する限り、__subclasshook__ を使用します
。定義されている 抽象クラスと同じメソッドがそのサブクラスとみなされます
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def say(self): return 'say yeah' @classmethod def __subclasshook__(cls, C): if cls is A: if any("say" in B.__dict__ for B in C.__mro__): return True return NotTmplementd class B(object): def say(self): return 'hello' print issubclass(B, A) # True print isinstance(B(), A) # True print B.__dict__ # {'say': <function say at 0x7f...>, ...} print A.__subclasshook__(B) # True
class D(A): def save(self, output, data): return output.write(data) if __name__ == '__main__': print issubclass(D, A) # print True print isinstance(D(), A) # raise TypeError
具象クラスで抽象基本クラスを使用する
import abc from cStringIO import StringIO class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def retrieve_values(self, input): pirnt 'base class reading data' return input.read() class B(A): def retrieve_values(self, input): base_data = super(B, self).retrieve_values(input) print 'subclass sorting data' response = sorted(base_data.splitlines()) return response input = StringIO("""line one line two line three """) reader = B() print reader.retrieve_values(input)
base class reading data subclass sorting data ['line one', 'line two', 'line three']
抽象属性 re
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractproperty def value(self): return 'should never get here.' class B(A): @property def value(self): return 'concrete property.' try: a = A() print 'A.value', a.value except Exception, err: print 'Error: ', str(err) b = B() print 'B.value', b.value
出力結果、抽象プロパティ Getter medhenod が 1 つしかないため、A をインスタンス化できません。
Error: ... print concrete property
りぃ
結果を出力する場合、具象クラスのプロパティを定義する場合、抽象プロパティと同じである必要があります。いずれか 1 つだけをオーバーライドした場合は機能しません。
import abc class A(object): __metaclass__ = abc.ABCMeta def value_getter(self): return 'Should never see this.' def value_setter(self, value): return value = abc.abstractproperty(value_getter, value_setter) class B(A): @abc.abstractproperty def value(self): return 'read-only' class C(A): _value = 'default value' def value_getter(self): return self._value def value_setter(self, value): self._value = value value = property(value_getter, value_setter) try: a = A() print a.value except Exception, err: print str(err) try: b = B() print b.value except Exception, err: print str(err) c = C() print c.value c.value = 'hello' print c.value
デコレータ構文を使用して、読み取りと書き込みの抽象プロパティを実装します。読み取りと書き込みのメソッドは同じである必要があります。
その他の Python 抽象クラスの定義と使用に関連する記事については、PHP 中国語 Web サイトに注目してください。