継承とポリモーフィズム

継承とポリモーフィズム–これはPythonの非常に重要な概念です。あなたが学びたいのなら、あなたはそれをよりよく理解しなければなりません。

継承

オブジェクト指向プログラミングの主な利点の1つは、再利用です。継承は、同じことを達成するためのメカニズムの1つです。継承により、プログラマーは最初に一般クラスまたは基本クラスを作成し、後でそれをより専門的なクラスに拡張できます。これにより、プログラマーはより良いコードを書くことができます。

継承を使用すると、基本クラスで使用可能なすべてのデータフィールドとメソッドを使用または継承できます。後で独自のメソッドとデータフィールドを追加できるため、継承により、コードを最初から書き直すのではなく、コードを整理する方法が提供されます。

オブジェクト指向の用語では、クラスXがクラスYを拡張する場合、Yはスーパー/親/基本クラスと呼ばれ、Xはサブクラス/子/派生クラスと呼ばれます。ここで注意すべき点の1つは、プライベートではないデータフィールドとメソッドのみが子クラスからアクセスできることです。プライベートデータフィールドとメソッドには、クラス内でのみアクセスできます。

派生クラスを作成するための構文は次のとおりです。

class BaseClass:
   Body of base class
class DerivedClass(BaseClass):
   Body of derived class

属性の継承

次の例を見てください-

出力

最初にDateというクラスを作成し、オブジェクトを引数として渡します。ここで、objectはPythonによって提供される組み込みクラスです。その後、timeという別のクラスを作成し、引数としてDateクラスを呼び出しました。この呼び出しを通じて、Dateクラスのすべてのデータと属性にTimeクラスにアクセスできます。そのため、以前に作成したTimeクラスオブジェクトtmからget_dateメソッドを取得しようとすると、可能になります。

Object.Attributeルックアップ階層

  • インスタンス
  • クラス
  • このクラスが継承するすべてのクラス

継承の例

継承の例をクロージャで見てみましょう-

例に参加するためのクラスをいくつか作成しましょう-

  • 動物-クラスは動物をシミュレートします
  • 猫-動物のサブクラス
  • 犬-動物のサブクラス

Pythonでは、オブジェクト(インスタンス)を作成し、属性に値を割り当てるために使用されるクラスのコンストラクター。

サブクラスのコンストラクターは、常に親クラスのコンストラクターに呼び出されて、親クラスの属性の値を初期化し、次にその属性の値の割り当てを開始します。

出力

上記の例では、すべてのサブクラスまたは子クラスが親クラスからそのプロパティを継承するように、親クラスに配置したコマンド属性またはメソッドを確認できます。

サブクラスが別のサブクラスからメソッドまたはデータを継承しようとすると、Dogクラスがそのcatクラスからswatstring()メソッドを呼び出そうとすると、エラーが発生します(この場合はAttributeErrorのように)。

ポリモーフィズム(「多くの形」)

ポリモーフィズムはPythonのクラス定義の重要な機能であり、クラスまたはサブクラス間でメソッドに共通の名前を付ける場合に使用されます。これにより、関数はさまざまなタイプのエンティティをさまざまな時間に使用できます。そのため、柔軟性と疎結合が提供されるため、コードを拡張して、長期にわたって簡単に保守できます。

これにより、関数は、クラス間の違いを意識することなく、これらのポリモーフィッククラスのオブジェクトを使用できます。

ポリモーフィズムは、サブクラスが基本クラスのメソッドを利用するか、それらをオーバーライドすることで、継承を通じて実行できます。

前の継承の例でポリモーフィズムの概念を理解し、両方のサブクラスにshow_affectionという1つの一般的なメソッドを追加しましょう-

私たちが見ることができる例から、それは異なるタイプのオブジェクトが同じ方法で、より具体的には同じメソッド(以下の例のshow_affection)のために同じ名前または共通のインターフェースのメソッドを持つ2つ以上のクラスを扱うことができるデザインを指しますどちらのタイプのオブジェクトでも呼び出されます。

出力

したがって、すべての動物は愛情を示します(show_affection)が、それらは異なります。したがって、「show_affection」の動作は、動物によって異なる動作をするという意味で多形性です。したがって、抽象的な「動物」の概念は実際には「show_affection」ではありませんが、特定の動物(犬や猫など)にはアクション「show_affection」の具体的な実装があります。

Python自体には、多態的なクラスがあります。たとえば、len()関数は複数のオブジェクトで使用でき、すべてが入力パラメーターに基づいて正しい出力を返します。

オーバーライド

Pythonでは、サブクラスにスーパークラスのメソッドをオーバーライドするメソッドが含まれている場合、次のように呼び出すことでスーパークラスのメソッドを呼び出すこともできます。

self.methodの代わりにSuper(Subclass、self).method。

class Thought(object):
   def __init__(self):
      pass
   def message(self):
      print("Thought, always come and go")

class Advice(Thought):
   def __init__(self):
      super(Advice, self).__init__()
   def message(self):
      print('Warning: Risk is always involved when you are dealing with market!')

コンストラクターの継承

前の継承の例からわかるように、子クラスの犬または猫には__init__メソッドが含まれていなかったため、__ init__はup 'の親クラスにありました。Pythonは、継承属性ルックアップを使用して、動物クラスで__init__を見つけました。子クラスを作成すると、最初に犬のクラスの__init__メソッドが検索され、次にそれが見つかりませんでした。次に、親クラスのAnimalが検索され、そこで検索されて呼び出されました。したがって、クラスの設計が複雑になったため、最初に親クラスコンストラクターを介してインスタンスを処理し、次に子クラスコンストラクターを介してインスタンスを初期化することをお勧めします。

出力

上記の例では、すべての動物に名前があり、すべての犬に特定の品種があります。親クラスコンストラクターをsuperで呼び出しました。したがって、犬には独自の__init__がありますが、最初に発生するのはスーパーと呼ばれることです。Superは組み込み関数であり、クラスをそのスーパークラスまたはその親クラスに関連付けるように設計されています。

この場合、dogのスーパークラスを取得し、ここで言うコンストラクター__init__にdogインスタンスを渡します。つまり、dogオブジェクトを使用して親クラスAnimal__init__を呼び出しています。犬のインスタンスでAnimal__init__とだけ言わないのはなぜかと疑問に思われるかもしれませんが、これは可能ですが、将来、動物クラスの名前が変更された場合に備えて。クラス階層を再配置して、犬が別のクラスから継承した場合はどうなりますか。この場合にsuperを使用すると、モジュール化を維持し、変更と保守を容易にすることができます。

したがって、この例では、一般的な__init__機能をより具体的な機能と組み合わせることができます。これにより、共通の機能を特定の機能から分離する機会が得られ、システム全体の設計を反映する方法で、コードの重複を排除し、クラスを相互に関連付けることができます。

結論

  • __init__は他の方法と同じです。継承できます

  • クラスに__init__コンストラクターがない場合、Pythonはその親クラスをチェックして、親クラスを見つけることができるかどうかを確認します。

  • Pythonはそれを見つけるとすぐにそれを呼び出し、検索を停止します

  • super()関数を使用して、親クラスのメソッドを呼び出すことができます。

  • 独自のクラスだけでなく、親でも初期化することをお勧めします。

多重継承とルックアップツリー

その名前が示すように、多重継承はPythonであり、クラスが複数のクラスから継承する場合です。

たとえば、子供は両方の親(母と父)から性格特性を継承します。

Pythonの多重継承構文

クラスが複数の親クラスから継承するようにするには、括弧内にこれらのクラスの名前を定義しながら派生クラスに書き込みます。これらの名前はコンマで区切ります。

以下はその例です-

>>> class Mother:
   pass

>>> class Father:
   pass

>>> class Child(Mother, Father):
   pass

>>> issubclass(Child, Mother) and issubclass(Child, Father)
True

多重継承とは、2つまたは3つ以上のクラスから継承する機能を指します。子が親から継承し、親が祖父母クラスから継承するため、複雑さが生じます。Pythonは、オブジェクトからの読み取りが要求されている属性を探して、継承ツリーに登ります。インスタンス内で、クラス内、次に親クラス、最後に祖父母クラスからチェックします。ここで、クラスが検索される順序(呼吸優先または深さ優先)で問題が発生します。デフォルトでは、Pythonは深さ優先で実行されます。

そのため、次の図では、PythonがクラスAで最初にdothis()メソッドを検索します。したがって、以下の例のメソッド解決順序は次のようになります。

Mro- D→B→A→C

以下の多重継承図を見てください-

Pythonの「mro」機能を理解するために例を見てみましょう。

出力

例3

「ひし形」の多重継承の別の例を見てみましょう。

上の図はあいまいと見なされます。前の例から、「メソッド解決順序」を理解します。つまり、mroはD→B→A→C→Aになりますが、そうではありません。Cから2番目のAを取得すると、Pythonは前のAを無視するため、この場合のmroはD→B→C→Aになります。

上の図に基づいて例を作成しましょう-

出力

上記の出力を理解するための簡単なルールは、同じクラスがメソッド解決順序で表示される場合、このクラスの以前の表示はメソッド解決順序から削除されるということです。

結論として-

  • どのクラスも複数のクラスから継承できます

  • Pythonは通常、継承クラスを検索するときに「深さ優先」順序を使用します。

  • ただし、2つのクラスが同じクラスから継承する場合、Pythonはそのクラスの最初の出現をmroから削除します。

デコレータ、静的メソッド、クラスメソッド

関数(またはメソッド)はdefステートメントによって作成されます。

ただし、メソッドは、メソッドの最初の引数がインスタンスオブジェクトである点を除いて、関数とまったく同じように機能します。

次のように、動作に基づいてメソッドを分類できます。

  • Simple method−クラス外で定義されています。この関数は、インスタンス引数を指定することでクラス属性にアクセスできます。

def outside_func(():
  • Instance method

def func(self,)
  • Class method −クラス属性を使用する必要がある場合

@classmethod
def cfunc(cls,)
  • Static method −クラスに関する情報がない

@staticmethod
def sfoo()

これまでインスタンスメソッドを見てきましたが、今度は他の2つのメソッドについての洞察を得るときです。

クラスメソッド

@classmethodデコレータは、呼び出されたクラスまたは最初の引数として呼び出されたインスタンスのクラスを渡す組み込み関数デコレータです。その評価の結果は、関数定義を覆い隠します。

構文

class C(object):
   @classmethod
   def fun(cls, arg1, arg2, ...):
      ....
fun: function that needs to be converted into a class method
returns: a class method for function

彼らはこのcls引数にアクセスでき、オブジェクトインスタンスの状態を変更することはできません。それには自己へのアクセスが必要です。

  • これは、クラスのオブジェクトではなく、クラスにバインドされます。

  • クラスメソッドは、クラスのすべてのインスタンスに適用されるクラスの状態を変更できます。

静的メソッド

静的メソッドはselfパラメーターもcls(class)パラメーターも取りませんが、他の任意の数のパラメーターを自由に受け入れることができます。

syntax

class C(object):
   @staticmethod
   def fun(arg1, arg2, ...):
   ...
returns: a static method for function funself.
  • 静的メソッドは、オブジェクトの状態もクラスの状態も変更できません。
  • アクセスできるデータが制限されています。

いつ何を使うか

  • 通常、クラスメソッドを使用してファクトリメソッドを作成します。ファクトリメソッドは、さまざまなユースケースのクラスオブジェクト(コンストラクタと同様)を返します。

  • 通常、静的メソッドを使用してユーティリティ関数を作成します。