Blow Up by Black Swan

Pythonークラス③(継承〜プライベートメソッド)

Pythonのクラス記事の最後になります。

最後は継承やデコレータ、プライベートメソッドについてです。

継承

継承は、オブジェクト指向の特徴のところでも触れたことですが、Pythonの場合は特にあるクラスの特徴を引き継ぐことくらいで捉えて良いと思います。クラス名の後ろにかっこを置き、継承したいクラス名を入れるだけです。

class クラス名(親クラス名):
    命令文

下がコード例です。 

#(例6)継承
class Test:
    def add_word(self):
        return "Hello"

class Child_Test(Test):                          #①継承(引数で親クラスを指定)
    def child_add_word(self, child_message):
        return Test().add_word() + child_message #親クラスのメソッドにアクセスしている

a = Child_Test()
a.child_add_word("World") #②子クラスの実行

戻り値

HelloWorld

ちなみに親クラスのメソッドにアクセスする記載の仕方は4つあります。(このコード例の場合だと、Child_Testクラス内のメソッドの戻り値を指定する部分です。)

  1. 親クラス名().メソッド名(): 親クラス名後にカッコをつける書き方(コード例に記載されているもの)
  2. 親クラス名.メソッド名(self, 引数): 親クラス名後にカッコは置かずメソッド名の後ろのカッコにselfを置く書き方
  3. super().メソッド名(): 親クラス名などの代わりにsuper()を置く書き方
  4. self.メソッド名(): 親クラスやsuper()の代わりにselfを先頭に置く書き方

この中で推奨されているものはあると思いますが、詳しくはわかりません。個人的には、①か③がシンプルかつトレースしやすく、わかりやすいと思います。ちなみに継承した場合に、親クラスと子クラスで同じ名前のメソッドなどがある場合の処理の優先順位ですが、あくまで子クラス内のものが優先されます。

多重継承

次は多重継承です。多重継承は、複数のクラスを継承するだけです。優先したいクラスから順に入力していくと良いでしょう。

class クラス名(親クラス1, 親クラス2,・・・):
    命令文

親クラス1から順々に読み込まれていきます。また、同一メソッド名がある場合も引数の順位が高いクラスから適用されます。イメージとしては、引数順位の高いクラスの中をかたっぱしから確認し(継承している場合は、継承しているクラスも含めて)、該当しない場合に次のクラスに行くというイメージです。

#(例7-1)多重継承
#参考サイト⑦
class Father:
    def add_word(self):
        return "Hello"
class Mother:
    def add_word2(self):
        return ", World!"

class Child(Father, Mother): #継承クラスを2つ設定
    def word(self):
        return Father().add_word() + Mother().add_word2()
a = Child()
a.word()                     #両継承クラスを反映した戻り値を返している

戻り値

Hello, World!

継承の優先順位を実際に確認されたいという方は、下記のコードをいじってみると面白いと思います。参考サイトであげているサイトに書かれていたコードを少し変えたものです。 

#(例7-2-1)多重継承(継承順位)
#参考サイト⑦
class Test1:
    def method(self):
        return "Test1"
class Test2:
    def method(self):
        return "Test2"
class Test3(Test1):
    def method(self):
        return "Test3"
class Test4(Test2, Test3): #Test2とTest3を継承。Test4はクラスとしての働きを持たない。
    pass
a = Test4()
a.method() #Test4で先に入力されたTest2のメソッドが実行される

戻り値

Test2

デコレータ

デコレータは、機能などを追加する役割を持ちます。クラスとは関係なく、生成することもできるので、Pythonを勉強している方だと既に知っている方もいると思います。

クラスメソッド

クラスで使う代表的なデコレータの一つが、クラスメソッドです。インスタンを作らずにクラス内のメソッドを実行できます。クラスメソッドの第1引数は、clsになります。

@classmethod
def メソッド名(cls):
    命令文
親クラス名.メソッド名 #指令実行のメソッド

下記がコード例です。 

#(例8-1-1)デコレータ・クラスメソッド
#参考サイト⑥
class Test:
    def __init__(self):
        self.value = "Hello"
    @classmethod            #①クラスメソッドの指定
    def add_word(cls, message2):
        return message2
Test.add_word("World")      #②インスタンス化せずにメソッドを利用できている。

戻り値

World

スタティックメソッド

次は、スタティックメソッドです。こちらは、クラスメソッドと違い、引数の指定がありません。 

@staticmethod
def メソッド名(引数):
    命令文
親クラス名.メソッド名 #指令実行のフォーマット

下記がコード例です。 

#クラス文(例8-2-1):デコレータ・スタティックメソッド
#参考サイト⑥
class Test:
    def __init__(self):
        self.value = "Hello"
    @staticmethod       #①スタティックメソッドの指定
    def add_word(message2):
        return message2
Test.add_word("World")    #②インスタンス化せずにメソッドを利用できている。

戻り値

World

プロパティメソッド

プロバティメソッドは、プロバティ関数やgetterなどとの絡みがあり、わたしもまだ理解しれていませんが、ざっくりいうと変数の値を変更されないようにするメソッドということになります。プロパティメソッドの場合は、インスタンス化処理が必要です。

@property
def メソッド名(self):
    命令文
変数名 = クラス名  #インスタンス化処理が必要
変数名.プロパティメソッド名   #カッコは不要

コード例です。 

#(例8-3-1)プロパティ
#参考サイト⑥、⑧
class Test:
    def __init__(self):
        self.value = "Hello"
    @property
    def word(self):
        return self.value
a = Test()
a.word

戻り値

Hello

a.wordに何らかの値を入れようとすると、上書きされずにエラーが立ちます。

パブリックとプライベート

オブジェクト指向の説明のところで触れたカプセル化を表現する方法です。上記で行った一般的なメソッドがパブリックメソッドです。そして今からやるのが、プライベートメソッドです。これは、内部でのみ参照されるメソッドを作る方法で、外部からのアクセスは遮断することで、メソッドや値の書き換えをできないようにしています。

プライベード

メソッド名の前にアンダーバーを2本入れ、第1引数はselfです。この処理をしたメソッドをプライベートメソッドと言います。

def __メソッド名(self, 引数):
    命令文

以下がコード例です。プライベートメソッドを呼び出そうとしています。

#(例9)プライベート
#参考サイト⑦
class Test:
    def __add_word(self): #①プライベートメソッドの設定
        return "Hello"
    def add_word(self, message):
        return self.__add_word() + ", " + message
a = Test()
a.__add_word() #②プライベートメソッドの呼び出し

実行しようとするとエラーが立ちます。

まとめ

以上がPythonのクラスの作り方です。そして、以下が参考にしたサイトです。こちらはクラス文について参考にしたサイトです。要所のコード例などで参考サイトと表記しているものと符号を一致させるようにしていますので、そちらも参考にしていください。もとからサイト参考にすれば良いじゃん!と言われそうですが、その理由は自分でブログを書こうと思った理由の1つにもなるのですが、色々なサイトを見ていて、それぞれ前提や求める技術水準がバラバラのため網羅性がなく、結果的によくわからなかったからです。

特に前提条件の違いは大きいなと感じました。当たり前のように使われている横文字がよくわからない。これが私が頻繁に感じたことで、今でも感じます。そこで、メタデータならぬ、メタブログ記事があったら面白いなと思い、ブログ記事で書いています。プログラミング初心者なので、その壁を乗り越えきれていないところは多々あると思いますが、どこかの初心者1人くらいには響くんじゃないかと思っています。冒頭で書いたように、私もまだまだわからないことばかりなので、ちょっとニュアンスや説明がおかしいところがあると思いますので、そこらへんはご愛嬌ということにして頂きつつ、こそっと教えてくれると嬉しいです。

こんな感じで、また次の題材を勉強して記事作っていきます。

参考サイト一覧

  1. 【Python入門】今さら聞けない!クラスの作り方と様々な使い方
  2. 【Python入門】Pythonにおけるclassの使い方とは?(プロスタ)
  3. 【Python入門】Pythonにおけるclassの使い方とは?
  4. Pythonの角括弧とドット表記の違いは何ですか?
  5. Pythonのクラス変数とインスタンス変数
  6. Python入門】デコレータの使い方まとめ (引数 複数 クラス)
  7. Python基礎講座(13 クラス)
  8. propertyについて