Python での抽象クラスの定義と使用

高洛峰
リリース: 2017-03-01 13:49:16
オリジナル
1456 人が閲覧しました

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__      # {&#39;say&#39;: <function say at 0x7f...>, ...}
print A.__subclasshook__(B) # True
ログイン後にコピー

不完全な実装

class D(A):
  def save(self, output, data):
    return output.write(data)

if __name__ == &#39;__main__&#39;:
  print issubclass(D, A)   # print True
  print isinstance(D(), A)  # raise TypeError
ログイン後にコピー

不完全な具体クラスを構築すると、Dがスローされます。抽象クラスと抽象クラスをインスタンス化できませんメソッド

具象クラスで抽象基本クラスを使用する

import abc 
from cStringIO import StringIO

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def retrieve_values(self, input):
    pirnt &#39;base class reading data&#39;
    return input.read()


class B(A):

  def retrieve_values(self, input):
    base_data = super(B, self).retrieve_values(input)
    print &#39;subclass sorting data&#39;
    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
[&#39;line one&#39;, &#39;line two&#39;, &#39;line three&#39;]
ログイン後にコピー

super を使用して抽象基本クラスのロジックを再利用できますが、サブクラスにオーバーライド メソッドの提供を強制することになります。

抽象属性 re

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractproperty
  def value(self):
    return &#39;should never get here.&#39;

class B(A):
  
  @property
  def value(self):
    return &#39;concrete property.&#39;

try:
  a = A()
  print &#39;A.value&#39;, a.value
except Exception, err:
  print &#39;Error: &#39;, str(err)

b = B()
print &#39;B.value&#39;, b.value
ログイン後にコピー

出力結果、抽象プロパティ Getter medhenod が 1 つしかないため、A をインスタンス化できません。

Error: ...
print concrete property
ログイン後にコピー

定義された抽象読み取りおよび書き込み属性

りぃ

結果を出力する場合、具象クラスのプロパティを定義する場合、抽象プロパティと同じである必要があります。いずれか 1 つだけをオーバーライドした場合は機能しません。

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  def value_getter(self):
    return &#39;Should never see this.&#39;

  def value_setter(self, value):
    return 

  value = abc.abstractproperty(value_getter, value_setter)

class B(A):
  
  @abc.abstractproperty
  def value(self):
    return &#39;read-only&#39;

class C(A):
  _value = &#39;default value&#39;

  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 = &#39;hello&#39;
print c.value
ログイン後にコピー

デコレータ構文を使用して、読み取りと書き込みの抽象プロパティを実装します。読み取りと書き込みのメソッドは同じである必要があります。

その他の Python 抽象クラスの定義と使用に関連する記事については、PHP 中国語 Web サイトに注目してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!