開発者ドキュメント

Python3でのクラス継承の理解

序章

オブジェクト指向プログラミングは、再利用可能なコードパターンを作成して、開発プロジェクトの冗長性を削減します。 オブジェクト指向プログラミングがリサイクル可能なコードを実現する1つの方法は、あるサブクラスが別の基本クラスのコードを活用できる場合の継承です。

このチュートリアルでは、親クラスと子クラスの動作、メソッドと属性のオーバーライド方法、Pythonでの継承の使用方法など、Pythonの継承の主要な側面について説明します。 super() 関数、および多重継承を利用する方法。

前提条件

Python 3をインストールし、コンピューターまたはサーバーにプログラミング環境をセットアップする必要があります。 プログラミング環境をセットアップしていない場合は、ローカルプログラミング環境またはサーバー上のプログラミング環境のインストールおよびセットアップガイドを参照して、オペレーティングに適したものにすることができます。システム(Ubuntu、CentOS、Debianなど)

継承とは何ですか?

継承は、クラスが別のクラス内で構築されたコードを使用する場合です。 生物学の観点から遺伝を考えると、子供が親から特定の特性を継承していると考えることができます。 つまり、子供は親の身長または目の色を継承できます。 子供は両親と同じ名前を共有することもできます。

子クラスまたはサブクラスと呼ばれるクラスは、親クラスまたは基本クラスからメソッドと変数を継承します。

と呼ばれる親クラスを考えることができます Parent クラス変数があります last_name, height、 と eye_color その子クラス Child から継承します Parent.

なぜなら Child サブクラスはから継承しています Parent 基本クラス、 Child クラスはのコードを再利用できます Parent、プログラマーが使用するコード行を減らし、冗長性を減らすことができます。

親クラス

親クラスまたは基本クラスは、子またはサブクラスの基になるパターンを作成します。 親クラスを使用すると、毎回同じコードを書き直すことなく、継承を通じて子クラスを作成できます。 どのクラスも親クラスにすることができるので、それらは単なるテンプレートではなく、それ自体で完全に機能するクラスです。

将軍がいるとしましょう Bank_account 持っている親クラス Personal_accountBusiness_account 子クラス。 個人口座とビジネス口座の間の方法の多くは、お金を引き出したり預けたりする方法など、類似しているため、それらはの親クラスに属することができます。 Bank_account. The Business_account サブクラスには、ビジネスレコードやフォームを収集する方法など、それに固有のメソッドがあります。 employee_identification_number 変数。

同様に、 Animal クラスは持っているかもしれません eating()sleeping() メソッド、および Snake サブクラスには、独自のサブクラスが含まれる場合があります hissing()slithering() メソッド。

を作成しましょう Fish 後でサブクラスとして魚のタイプを構築するために使用する親クラス。 これらの魚のそれぞれは、特徴に加えて、名と姓を持ちます。

情報:このチュートリアルのサンプルコードに従うには、ローカルシステムでPythonインタラクティブシェルを開いて、 python3 指図。 次に、例の後に追加して、例をコピー、貼り付け、または編集できます。 >>> 促す。

という新しいファイルを作成します fish.py そして、 __ init __()コンストラクターメソッドから始めます。 first_namelast_name それぞれのクラス変数 Fish オブジェクトまたはサブクラス。

fish.py
class Fish:
    def __init__(self, first_name, last_name="Fish"):
        self.first_name = first_name
        self.last_name = last_name

初期化済み last_name 文字列を持つ変数 "Fish" ほとんどの魚の名前がこれになることがわかっているからです。

他のメソッドもいくつか追加しましょう。

fish.py
class Fish:
    def __init__(self, first_name, last_name="Fish"):
        self.first_name = first_name
        self.last_name = last_name

    def swim(self):
        print("The fish is swimming.")

    def swim_backwards(self):
        print("The fish can swim backwards.")

メソッドを追加しました swim()swim_backwards()Fish クラス。これにより、すべてのサブクラスもこれらのメソッドを利用できるようになります。

作成する魚のほとんどは、軟骨魚ではなく硬骨魚(骨格が骨でできているため)と見なされるためです。軟骨で作られた骨格)、さらにいくつかの属性を追加することができます __init__() 方法:

fish.py
class Fish:
    def __init__(self, first_name, last_name="Fish",
                 skeleton="bone", eyelids=False):
        self.first_name = first_name
        self.last_name = last_name
        self.skeleton = skeleton
        self.eyelids = eyelids

    def swim(self):
        print("The fish is swimming.")

    def swim_backwards(self):
        print("The fish can swim backwards.")

親クラスの構築は、他のクラスの構築と同じ方法論に従いますが、子クラスを作成した後、子クラスがどのメソッドを使用できるかを検討している点が異なります。

子クラス

子またはサブクラスは、親クラスから継承するクラスです。 つまり、各子クラスは親クラスのメソッドと変数を利用できるようになります。

たとえば、 Goldfish サブクラス化する子クラス Fish クラスはを利用できるようになります swim() で宣言されたメソッド Fish 宣言する必要はありません。

各子クラスは、親クラスのクラスであると考えることができます。 つまり、という子クラスがある場合 Rhombus と呼ばれる親クラス Parallelogram、私たちはそれを言うことができます Rhombus です Parallelogram、ちょうど Goldfish です Fish.

子クラスの最初の行は、親クラスをパラメーターとして子クラスに渡す必要があるため、非子クラスとは少し異なります。

class Trout(Fish):

The Trout クラスはの子です Fish クラス。 単語が含まれているので、これを知っています Fish 括弧内。

子クラスでは、メソッドを追加するか、既存の親メソッドをオーバーライドするか、デフォルトの親メソッドを受け入れるかを選択できます。 pass この場合に実行するキーワード:

fish.py
...
class Trout(Fish):
    pass

これで、 Trout 追加のメソッドを定義する必要なしにオブジェクト。

fish.py
...
class Trout(Fish):
    pass

terry = Trout("Terry")
print(terry.first_name + " " + terry.last_name)
print(terry.skeleton)
print(terry.eyelids)
terry.swim()
terry.swim_backwards()

作成しました Trout 物体 terry それはのそれぞれの方法を利用します Fish これらのメソッドをで定義しなかったとしても、クラス Trout 子クラス。 の値を渡すだけで済みました "Terry"first_name 他のすべての変数が初期化されたため、変数。

プログラムを実行すると、次の出力が表示されます。

Output
Terry Fish bone False The fish is swimming. The fish can swim backwards.

次に、独自のメソッドを含む別の子クラスを作成しましょう。 このクラスを呼びます Clownfish、そしてその特別な方法はそれがイソギンチャクと一緒に暮らすことを可能にします:

fish.py
...
class Clownfish(Fish):

    def live_with_anemone(self):
        print("The clownfish is coexisting with sea anemone.")

次に、を作成しましょう Clownfish これがどのように機能するかを確認するためのオブジェクト:

fish.py
...
casey = Clownfish("Casey")
print(casey.first_name + " " + casey.last_name)
casey.swim()
casey.live_with_anemone()

プログラムを実行すると、次の出力が表示されます。

Output
Casey Fish The fish is swimming. The clownfish is coexisting with sea anemone.

出力は、 Clownfish 物体 casey 使用することができます Fish メソッド __init__()swim() の子クラスメソッドと同様に live_with_anemone().

使用しようとすると live_with_anemone() のメソッド Trout オブジェクト、エラーを受け取ります:

Output
terry.live_with_anemone() AttributeError: 'Trout' object has no attribute 'live_with_anemone'

これは、メソッドが live_with_anemone() にのみ属します Clownfish 子クラスであり、 Fish 親クラス。

子クラスは、それが属する親クラスのメソッドを継承するため、各子クラスはプログラム内でそれらのメソッドを利用できます。

親メソッドのオーバーライド

これまで、子クラスを見てきました Trout それを利用した pass すべての親クラスを継承するキーワード Fish 行動、および別の子クラス Clownfish これは、すべての親クラスの動作を継承し、子クラスに固有の独自のメソッドも作成しました。 ただし、親クラスの動作のすべてではなく、一部を使用したい場合があります。 親クラスのメソッドを変更すると、それらをオーバーライドします。

親クラスと子クラスを作成するときは、オーバーライドによって不要なコードや冗長なコードが生成されないように、プログラムの設計を念頭に置くことが重要です。

作成します Shark の子クラス Fish 親クラス。 作成したので Fish 私たちが主に硬骨魚を作るという考えを持ったクラスでは、調整を行う必要があります Shark 代わりに軟骨魚であるクラス。 プログラムの設計に関しては、硬骨魚以外の魚が複数いる場合は、これら2種類の魚ごとに別々のクラスを作成することをお勧めします。

サメは硬骨魚とは異なり、骨ではなく軟骨でできた骨格を持っています。 また、まぶたがあり、後ろ向きに泳ぐことはできません。 ただし、サメは沈むことで後方に移動することができます。

これに照らして、オーバーライドします __init__() コンストラクターメソッドと swim_backwards() 方法。 変更する必要はありません swim() サメは泳ぐことができる魚なので、方法。 この子クラスを確認しましょう:

fish.py
...
class Shark(Fish):
    def __init__(self, first_name, last_name="Shark",
                 skeleton="cartilage", eyelids=True):
        self.first_name = first_name
        self.last_name = last_name
        self.skeleton = skeleton
        self.eyelids = eyelids

    def swim_backwards(self):
        print("The shark cannot swim backwards, but can sink backwards.")

初期化されたパラメータをオーバーライドしました __init__() メソッド、そのように last_name 変数が文字列と等しく設定されるようになりました "Shark"skeleton 変数が文字列と等しく設定されるようになりました "cartilage"、 そしてその eyelids 変数がブール値に設定されるようになりました True. クラスの各インスタンスは、これらのパラメーターをオーバーライドすることもできます。

方法 swim_backwards() 内の文字列とは異なる文字列を出力するようになりました Fish サメは硬骨魚のように後ろ向きに泳ぐことができないため、親クラスです。

これで、のインスタンスを作成できます Shark 子クラス、これはまだ利用します swim() の方法 Fish 親クラス:

fish.py
...
sammy = Shark("Sammy")
print(sammy.first_name + " " + sammy.last_name)
sammy.swim()
sammy.swim_backwards()
print(sammy.eyelids)
print(sammy.skeleton)

このコードを実行すると、次の出力が返されます。

Output
Sammy Shark The fish is swimming. The shark cannot swim backwards, but can sink backwards. True cartilage

The Shark 子クラスは正常にオーバーライドしました __init__()swim_backwards() の方法 Fish 親クラス、また継承している間 swim() 親クラスのメソッド。

他のクラスよりも一意な子クラスの数が限られている場合は、親クラスのメソッドをオーバーライドすると便利です。

The super() 関数

とともに super() 関数を使用すると、クラスオブジェクトで上書きされた継承されたメソッドにアクセスできます。

私たちが使用するとき super() 関数では、親メソッドを子メソッドに呼び出して使用します。 たとえば、親メソッドの1つの側面を特定の機能でオーバーライドした後、元の親メソッドの残りの部分を呼び出してメソッドを終了したい場合があります。

生徒を評価するプログラムでは、子供向けのクラスが必要になる場合があります Weighted_grade から継承します Grade 親クラス。 子供のクラスで Weighted_grade、オーバーライドしたい場合があります calculate_grade() 加重グレードを計算する機能を含めるための親クラスのメソッド。ただし、元のクラスの残りの機能は保持します。 を呼び出すことによって super() 機能これを達成することができます。

The super() 関数は、 __init__() メソッドは、子クラスに一意性を追加してから、親からの初期化を完了する必要がある可能性が高いためです。

これがどのように機能するかを確認するために、 Trout 子クラス。 マスは通常淡水魚なので、追加しましょう water に可変 __init__() メソッドとそれを文字列と等しく設定します "freshwater"、ただし、親クラスの残りの変数とパラメーターを維持します。

fish.py
...
class Trout(Fish):
    def __init__(self, water = "freshwater"):
        self.water = water
        super().__init__(self)
...

オーバーライドしました __init__() のメソッド Trout 子クラス、の異なる実装を提供します __init__() 親クラスによってすでに定義されている Fish. 以内 __init__() 私たちの方法 Trout 明示的に呼び出したクラス __init__() の方法 Fish クラス。

メソッドをオーバーライドしたため、パスする必要がなくなりました first_name パラメータとしてで Trout、パラメータを渡した場合、リセットされます freshwater 代わりは。 したがって、初期化します first_name オブジェクトインスタンスで変数を呼び出すことによって。

これで、親クラスの初期化された変数を呼び出し、一意の子変数を利用することもできます。 これを次のインスタンスで使用してみましょう Trout:

fish.py
...
terry = Trout()

# Initialize first name
terry.first_name = "Terry"

# Use parent __init__() through super()
print(terry.first_name + " " + terry.last_name)
print(terry.eyelids)

# Use child __init__() override
print(terry.water)

# Use parent swim() method
terry.swim()
Output
Terry Fish False freshwater The fish is swimming.

出力は、オブジェクトが terryTrout 子クラスは、子固有の両方を利用できます __init__() 変数 water を呼び出すこともできます Fish__init__() の変数 first_name, last_name、 と eyelids.

組み込みのPython関数 super() 子クラスでこれらのメソッドの特定の側面をオーバーライドする場合でも、親クラスのメソッドを利用できます。

多重継承

多重継承は、クラスが複数の親クラスから属性とメソッドを継承できる場合です。 これにより、プログラムの冗長性を減らすことができますが、ある程度の複雑さとあいまいさをもたらす可能性もあるため、プログラム全体の設計を考慮して行う必要があります。

多重継承がどのように機能するかを示すために、 Coral_reef から継承するよりも子クラス Coral クラスと Sea_anemone クラス。 それぞれにメソッドを作成してから、 pass のキーワード Coral_reef 子クラス:

coral_reef.py
class Coral:

    def community(self):
        print("Coral lives in a community.")


class Anemone:

    def protect_clownfish(self):
        print("The anemone is protecting the clownfish.")


class CoralReef(Coral, Anemone):
    pass

The Coral クラスにはというメソッドがあります community() 1行を印刷し、 Anemone クラスにはというメソッドがあります protect_clownfish() 別の行を印刷します。 次に、両方のクラスを継承tupleに呼び出します。 この意味は CoralReef 2つの親クラスから継承しています。

今すぐインスタンス化しましょう CoralReef 物体:

coral_reef.py
...
great_barrier = CoralReef()
great_barrier.community()
great_barrier.protect_clownfish()

オブジェクト great_barrier として設定されます CoralReef オブジェクトであり、両方の親クラスのメソッドを使用できます。 プログラムを実行すると、次の出力が表示されます。

Output
Coral lives in a community. The anemone is protecting the clownfish.

出力は、両方の親クラスのメソッドが子クラスで効果的に使用されたことを示しています。

多重継承により、子クラスの複数の親クラスからのコードを使用できます。 同じメソッドが複数の親メソッドで定義されている場合、子クラスはタプルリストで宣言された最初の親のメソッドを使用します。

効果的に使用できますが、プログラムが曖昧になったり、他のプログラマーが理解しにくくなったりしないように、多重継承は注意して行う必要があります。

結論

このチュートリアルでは、親クラスと子クラスを作成し、子クラス内の親メソッドと属性をオーバーライドして、 super() 関数、および子クラスが複数の親クラスから継承できるようにします。

オブジェクト指向コーディングの継承により、ソフトウェア開発のDRY(自分自身を繰り返さないでください)の原則を順守できるようになり、少ないコードと繰り返しでより多くのことを実行できるようになります。 また、継承により、プログラマーは、コードが効果的で明確であることを確認するために、作成しているプログラムをどのように設計しているかについて考える必要があります。

モバイルバージョンを終了