継承、抽象基本クラス、Pythonのインターフェイスの関係を1文に要約します。Pythonのインターフェイスメカニズムは抽象基本クラスを通じて実現でき、インターフェイスの実現は継承メカニズムに依存します。
1.継承
継承は、オブジェクト指向プログラミング言語の3つの特性の1つです(他の2つは、カプセル化とポリモーフィズムです)。いわゆる継承とは、サブクラスが自動的に親クラスによって定義されたメソッドと属性を持ち、サブクラスが同じ名前のメソッドを繰り返し定義する必要がないことを意味します。または属性です。継承の最大の利点の1つは、コードの再利用の度合いを改善できることです。
1.一般的なシリーズの場合
ここでは、Pythonの継承の概念を紹介します。これは、高校の数学における重要な概念である数値のシーケンスです。シーケンスは、一連の値で構成されるシーケンスです。シーケンスの各値は、シーケンス内の前のアイテムまたは複数のアイテムによって異なります。次に例を示します。
- 算術シーケンスの場合、シーケンスの2番目の項目から始まり、各項目は前の項目に固定定数を追加することによって取得されます。
- 幾何学的シーケンスの場合、シーケンスの2番目の項から開始して、各項は前の項に固定定数を乗算することによって取得されます。
- フィボナッチシーケンスの場合、シーケンスの3番目のアイテムから始まり、各アイテムには最初の2つのアイテムの合計があります。
オブジェクト指向の機能を使用して、上記の異なるタイプのシリーズのコードを抽象化する必要がある場合、3つのシリーズのシリーズは、類似の機能を持つ以下のメソッドをサポートする必要があると想像できます。
- 初期化メソッド:シーケンスの最初の数項目を初期化するために使用されます。
- 走査サポート方法:反復可能な方法でシーケンスの項目の走査をサポートできます。
- シーケンスアイテムの生成方法:特定のルールに従って、最初のいくつかのアイテムに従って任意のアイテムを生成します。
継承の方法が採用されていない場合、各シーケンスクラスの最終的な実現は、高度なコードの繰り返しになります。
2.一般的なシーケンスの実現
上記の議論に対応して、継承を使用して各シーケンスクラスを実装することを検討してください。
- まず、一般的なシーケンスの親クラスを定義
Progression
します。このシーケンスでは、シーケンスの一般的なメソッドと実用的なメソッドが実現されます。 - 次に、継承された
Progression
クラスは、親クラスメソッドを書き換えるか、シーケンスの一般的な用語の生成規則に従って、算術、等比、およびフィボナッチシーケンスで新しいメソッドを定義します。
基本クラス
シーケンス基本クラスでは:
__init__
初期化メソッドはstart
、シーケンスの最初の項目の値を指定するため、およびnum
デフォルトで印刷されるシーケンス項目の数を指定するために2つのパラメーターを受け取ります。これらはそれぞれ_current
合計_num
値を初期化するために使用されます。_advance
このメソッドは、番号シーケンスの一般的なルールに従ってアイテムを生成するために使用されます。__iter__
また、__next__
メソッドは、Pythonの反復子プロトコルをサポートするために使用されます(詳細については、Pythonのforループ操作メカニズムの探索と反復可能なオブジェクトと反復子の詳細な説明を参照してください)。__str__
このメソッドは、シーケンスオブジェクトをリストに変換し、リストの文字列表現を返すために使用されます。
class Progression:
"""数列基类"""
def __init__(self, start=0, num=10):
"""
将当前数列的第一项初始化为0
:param start: 数列第一项,默认为0
:param num: 打印数列时的默认显示项数
"""
self._current = start
self._num = num
def _advance(self):
"""用于根据数列前若干项进行任意项的生成,该方法应该被子类重写"""
self._current += 1
def __next__(self):
"""迭代器协议方法,返回数列中的下一项,当已至数列最后一项则抛出StopIteration异常"""
if self._num > 0:
ans = self._current
self._advance()
self._num -= 1
return ans
else:
raise StopIteration
def __iter__(self):
"""迭代器协议方法,返回对象自身"""
return self
def __str__(self):
"""返回对象的字符串表示形式"""
return str(list(self))
算術シーケンス
継承されたProgression
クラスによる算術シーケンスの実現では、次のようになります。
__init__
このメソッドでは、親クラス初期化メソッドが呼び出され、親クラスから継承_current
され、デフォルト_num
で出力されるシーケンス項目の数を初期化し、このクラスに固有の算術シーケンス定数も初期化し_increment
ます。_advance
このメソッドは、算術シーケンスの一般的な規則に従って、同じ名前の親メソッドを書き換えます。__next__
、__iter__
そして__str__
メソッドはProgression
クラスから継承され、コードを書き直す必要はありません。
class ArithmeticProgression(Progression):
"""等差数列"""
def __init__(self, start=0, increment=1, num=10):
"""
创建一个新的等差数列
:param increment: 等差常量,默认为1
:param start: 数列首项,默认为0
:param num: 打印数列时的默认显示项数
"""
super().__init__(start=start, num=num)
self._increment = increment
def _advance(self): # 重写父类同名方法
"""根据等差数列通项规则,生成任意项"""
self._current += self._increment
幾何学的シーケンス
継承されたProgression
クラスのため、幾何学的シーケンスの実現では、次のようになります。
__init__
このメソッドでは、親クラス初期化メソッドが呼び出されて、親クラスから継承_current
され、デフォルト_num
で出力されるシーケンス項目の数を初期化し、このクラスに固有の幾何学的シーケンス定数も初期化し_base
ます。_advance
このメソッドは、ジオメトリックシーケンスの一般的なルールに従って、親クラスの同じ名前のメソッドを書き換えます。__next__
、__iter__
そして__str__
メソッドはProgression
クラスから継承され、コードを書き直す必要はありません。
class GeometricProgression(Progression):
"""等比数列"""
def __init__(self, start=1, num=10, base=2):
"""
创建一个新的等比数列
:param base: 等比常量,默认值为2
:param start: 数列首项,默认为1
:param num: 打印数列时的默认显示项数
"""
super().__init__(start=start, num=num)
self._base = base
def _advance(self):
"""根据等比数列通项规则,生成任意项"""
self._current *= self._base
フィボナッチ数列
フィボナッチ数列の実現では、Progression
クラスを継承するため、次のようになります。
__init__
親クラスの初期化メソッドは、親クラスから継承_current
され、デフォルト_num
で出力されるシーケンスアイテムの数を初期化するメソッドで呼び出され、クラスに固有の仮想アイテム0も初期化し_prev
ます。_advance
このメソッドは、フィボナッチ数列の一般的な規則に従って、親クラスの同じ名前のメソッドを書き換えます。__next__
、__iter__
そして__str__
メソッドはProgression
クラスから継承され、コードを書き直す必要はありません。
class FibonacciProgression(Progression):
"""斐波那契数列"""
def __init__(self, first=0, second=1, num=10):
"""
创建一个新的斐波那契数列
:param first: 数列第一项,默认为0
:param second: 数列第二项,默认为1
:param num: 打印数列时的默认显示项数
"""
super().__init__(start=first, num=num)
self._prev = second - first # 假想在第一项之前存在的第零项
def _advance(self):
"""根据斐波那契数列通项规则,生成任意项"""
self._prev, self._current = self._current, self._prev + self._current
以下は、上記の一連の実現クラスのテスト結果です。
if __name__ == '__main__':
print('默认数列Progression:')
print(Progression(num=5), end='\n'*2) # [0, 1, 2, 3, 4]
print('等差数列ArithmeticProgression:')
print(ArithmeticProgression(start=10, increment=3, num=7), end='\n'*2) # [10, 13, 16, 19, 22, 25, 28]
print('等比数列GeometricProgression:')
print(GeometricProgression(start=4, base=3, num=9), end='\n'*2) # [4, 12, 36, 108, 324, 972, 2916, 8748, 26244]
print('斐波那契数列FibonacciProgression:')
print(FibonacciProgression(first=2, num=12)) # [2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199]
2、抽象基本クラス
上記のコードを注意深く分析すると、基本クラスProgression
はArithmeticProgression
、GeometricProgression
および基本クラスはとして意図さFibonacciProgression
れていますが、インスタンス化によってProgression
オブジェクトが提供されますが、これはArithmeticProgression
特別なケースにすぎないため、あまり重要ではありません。つまり、最初の項は0です。算術定数が1の算術シーケンス。
オブジェクト指向プログラミングパラダイムをサポートする言語でProgression
は、このクラスには、複数のサブクラスが実装する必要があるメソッドを指定するために基本クラスとしてのみ使用される特別な用語があります。抽象基本クラス。
Python3で抽象基本クラスを定義する場合は、次の手順で行うことができます。
- 抽象基本クラスを定義する前に、モジュールから
abc
クラスABCMeta
とメソッドをインポートしますabstractmethod
。 - 抽象基本クラスを定義する場合:
- 抽象基本クラス名の後に指定
metaclass
しABCMeta
ます。 - これは、抽象基本クラスがサブクラスによって継承される必要があるメソッド(一般に抽象メソッドと呼ばれます)の前に使用され
@abstractmethod
ます。
- 抽象基本クラス名の後に指定
例:前述のように、Progression
メソッドの場合、上記のプロセスに従ってそれを抽象基本クラスとして定義するコードは次のとおりです。
from abc import ABCMeta, abstractmethod
class Progression(metaclass=ABCMeta):
"""数列基类"""
def __init__(self, start=0, num=10):
"""
将当前数列的第一项初始化为0
:param start: 数列第一项,默认为0
:param num: 打印数列时的默认显示项数
"""
self._current = start
self._num = num
@abstractmethod
def _advance(self):
"""用于根据数列前若干项进行任意项的生成,该方法应该被子类重写"""
def __next__(self):
"""迭代器协议方法,返回数列中的下一项,当已至数列最后一项则抛出StopIteration异常"""
if self._num > 0:
ans = self._current
self._advance()
self._num -= 1
return ans
else:
raise StopIteration
def __iter__(self):
"""迭代器协议方法,返回对象自身"""
return self
def __str__(self):
"""返回对象的字符串表示形式"""
return str(list(self))
上記のコードで抽象メソッドを_advance
定義することがわかります。これは、一方でこのメソッドがすべてのサブクラスに存在する必要があり、他方で、すべてのサブクラスでのこのメソッドの実装が完全に異なるためです。
のために、ことに留意すべきである抽象基底クラス(例えばProgression
、それ以外の場合は、このようなエラーを報告します、それは直接オブジェクトを作成することにより、インスタンス化することはできません): TypeError: Can't instantiate abstract class Progression with abstract methods _advance
。
3、インターフェース
インターフェイスは、さまざまなコード作成者が次のことを実行できるようにするプログラミングメカニズムです。
- 同じコードシグネチャ(メソッド名(
_advance
)、パラメーター、戻り値など)に従います。 - 算術、幾何比、フィボナッチ数列の一般的な用語に基づいてルールを生成する
_advance
方法など、さまざまなアルゴリズムを使用して特定のコードを実装します。
インターフェイスメカニズムの利点は、次のことができることです。
- たとえば、アプリケーションアーキテクトは全体的なフレームワークを構築し、特定の実装は実装スタッフに任せることができます。これは、上司が一般的に手元のリソースに基づいて特定のことを行うように指示しているようです物事と期待される結果とは何か、そしてあなたとあなたの同僚は、特定のプロセスを通じて各物事を実装するために一生懸命取り組む必要があります。
- コード間の疎結合を実現するために、各インターフェイスの実装担当者は、他の担当者によるインターフェイスの内部固有の実装を知る必要はありません。
Pythonでは、サブクラスが抽象基本クラスを継承し、その中のすべての抽象メソッドを実装する限り、インターフェイスの特定の実装用。
以下は、インターフェース実装プロセスを示すための上記のシーケンスクラスの例です。
from abc import ABCMeta, abstractmethod
class Progression(metaclass=ABCMeta):
"""数列基类"""
def __init__(self, start=0, num=10):
"""
将当前数列的第一项初始化为0
:param start: 数列第一项,默认为0
:param num: 打印数列时的默认显示项数
"""
self._current = start
self._num = num
@abstractmethod
def _advance(self):
"""用于根据数列前若干项进行任意项的生成,该方法应该被子类重写"""
def __next__(self):
"""迭代器协议方法,返回数列中的下一项,当已至数列最后一项则抛出StopIteration异常"""
if self._num > 0:
ans = self._current
self._advance()
self._num -= 1
return ans
else:
raise StopIteration
def __iter__(self):
"""迭代器协议方法,返回对象自身"""
return self
def __str__(self):
"""返回对象的字符串表示形式"""
return str(list(self))
class FibonacciProgression(Progression):
"""斐波那契数列"""
def __init__(self, first=0, num=10, second=1):
"""
创建一个新的斐波那契数列
:param first: 数列第一项,默认为0
:param second: 数列第二项,默认为1
:param num: 打印数列时的默认显示项数
"""
super().__init__(start=first, num=num)
self._prev = second - first # 假想在第一项之前存在的第零项
def _advance(self):
"""根据斐波那契数列通项规则,生成任意项"""
self._prev, self._current = self._current, self._prev + self._current
if __name__ == '__main__':
print(FibonacciProgression(first=2, num=12)) # [2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199]