Python

【Python】クラスの定義方法と使い方を解説

この記事では、Pythonのclass(クラス)について解説します。

クラスとは、つまりは「」のことです。クラスを定義することで int型 や str型 と同じような便利な型を自ら作ることができます。

ちなみに、元から言語が用意してくれている型を「組み込み型」と呼び、ユーザーが定義した型のことを「ユーザー定義型」と呼びます。そのまんまですね!

型ってなんだっけ?

データの性質を定めて取り扱い方を定義したもの

それでは、クラスの使い方を見ていきましょう!

クラスの使い方

クラスは 以下のような手順で使用します。

  • STEP1
    クラスを定義する

    クラスは classキーワード を使って定義します。

    class クラス名:
        # 何かしらの処理

    クラス名の頭文字には大文字を使いましょう。また、複数の単語がくっついた名前を使用する場合は、単語の頭文字を大文字にします。例えば MyClass みたいな感じです。

    クラスの中には「コンストラクタ」や「メソッド」を定義しますが詳しくは後述します。

  • STEP2
    インスタンス化

    クラスを使うには、そのクラスのインスタンスを生成する必要があります。

    インスタンスとは?

    クラスを元に生成したデータのこと

    インスタンスを生成するには、以下のようにクラスを呼び出します。

    インスタンス名 = クラス名()

    このようにクラスのインスタンスを生成することをインスタンス化と呼びます。1つのクラスからインスタンスはいくつでも生成することができます。

  • STEP3
    クラスの機能を呼び出す

    インスタンス化したことにより「インスタンス変数(クラスに定義されている変数)」「メソッド(クラスに定義されている関数)」を呼び出すことができます。

    インスタンス変数やメソッドを呼び出すには、インスタンス名と呼び出すインスタンス変数名やメソッド名を .(ドット) で繋いで呼び出します。

    インスタンス名.変数名
    
    インスタンス名.メソッド名()

    インスタンス変数とメソッドについては後述します。

このような流れでクラスは使用されます。

インスタンスについて

クラスとインスタンスの例え話としてたい焼きの話をよく目にします。

タイヤキを焼く鉄板がクラスで、タイヤキがインスタンスとして表されます。これは、鉄板(クラス)さえ作ってしまえば、タイヤキ(インスタンス)はいくらでも生成できるということです。そして、タイヤキ(インスタンス)の中身はタイヤキによって変更することができます。

この例え話をコードとして表すと以下のようになります。
※ 今回はわかりやすさを重視してクラス名や変数名を日本語で記述しました

# タイヤキクラス
class タイヤキ:
    def __init__(self, 中身):
        self.中身 = 中身

# インスタンス生成
あんこタイヤキ = タイヤキ('あんこ')
カスタードタイヤキ = タイヤキ('カスタード')

print(あんこタイヤキ.中身)
# あんこ

print(カスタードタイヤキ.中身)
# カスタード

上記のコードは、タイヤキクラスから「あんこタイヤキインスタンス」と「カスタードタイヤキインスタンス」を生成し、中身を出力しています。このように、一度クラスを作ってしまえば何度でもインスタンスを生成することができます。

コンストラクタ(イニシャライザ)

コンストラクタは、クラスをインスタンス化する際に呼び出されます。インスタンスを初期化する際の処理を定義できます。

定義

コンストラクタは __init__ という特殊メソッドを使って定義します。

class クラス名:
    # コンストラクタ
    def __init__(self):
        # なんらかの処理

以下のように引数を受け取ることもできます。

class クラス名:
    # コンストラクタ
    def __init__(self, 引数1, 引数2, ..., 引数N):
        # なんらかの処理

呼び出し

引数が定義されている場合は、インスタンス化する際に値を渡す必要があります。

# コンストラクタに引数が定義されていない場合
インスタンス名 = クラス名()

# コンストラクタに引数が定義されている場合はその分だけ値を渡す
インスタンス名 = クラス名(値1, 値2, ..., 値N)

サンプル

試しにコンストラクタを定義し、インスタンス化してみましょう!

class TestClass:
    # コンストラクタ
    def __init__(self):
        print('TestClassのコンストラクタが呼び出されました!')


# TestClassのインスタンス化
tc = TestClass()

実行結果

TestClassのコンストラクタが呼び出されました!

ちなみにコンストラクタは「イニシャライザ」とも呼ばれ、特に何も定義しないならば省略することもできます。

デストラクタ

デストラクタは、インスタンスが削除される際に呼び出されます。

定義

デストラクタは __del__ という特殊メソッドを使って定義します。

class クラス名:
    # デストラクタ
    def __del__(self):
        #何かしらの処理

サンプル

試しにデストラクタを定義して使ってみましょう!

class Test:
    # デストラクタ
    def __del__(self):
        print('デストラクタが呼び出されました!')


t = Test()

print('-'*30)
# del文でインスタンスを削除
del t
print('-'*30)

実行結果

------------------------------
デストラクタが呼び出されました!
------------------------------

このサンプルでは del文 を使って明示的にインスタンスを削除しましたが、プログラム終了時にはインスタンスも削除されるのでデストラクタが呼び出されます。

selfとは?

先ほどのコンストラクタやデストラクタに定義されていた self という引数が気になったかと思います。

self は、自分自身(インスタンス)にアクセスするためのものです。クラスに定義されたコンストラクタやデストラクタを含めたメソッドは基本的に self引数 を持ちます。

以下のコードでは self とインスタンスを出力しています。

class Test:

    def __init__(self):
        # selfの出力
        print(self)


test = Test()
# インスタンスの出力
print(test)

実行結果

<__main__.Test object at 0x1039994d0>
<__main__.Test object at 0x1039994d0>

selftestインスタンス は、まったく同じ値が出力がされたので self はインスタンスにアクセスしていることが確認できました!

インスタンスにアクセスすることでクラス内で自身の機能(インスタンス変数やメソッド)を使うことができます。

self の使い方については都度で解説するので、ここでは「self は自身のインスタンスにアクセスしてるんだ〜」という認識で構いません。

クラスに定義できる変数

クラスには、2種類の変数を定義することができます。

インスタンス変数

インスタンス変数は、インスタンス化しなければ呼び出せない変数です。

定義

インスタンス変数を定義するには、コンストラクタ内で self を用いて定義します。

class クラス名:
    def __init__(self):
        self.インスタンス変数名 = 初期値

もちろん、引数の値を渡すこともできます。

class クラス名:
    def __init__(self, 引数):
        self.インスタンス変数名 = 引数

呼び出し

インスタンス変数を呼び出すに以下のようにします。

インスタンス名.インスタンス変数名

サンプル

試しにいくつかインスタンス変数を定義して出力してみましょう。

class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


mike = Person('Mike', 14, '男')
print(f'名前: {mike.name}, 年齢: {mike.age}, 性別: {mike.gender}')

elizabeth = Person('Elizabeth', 36, '女')
print(f'名前: {elizabeth.name}, 年齢: {elizabeth.age}, 性別: {elizabeth.gender}')

実行結果

名前: Mike, 年齢: 14, 性別: 男
名前: Elizabeth, 年齢: 36, 性別: 女

動的な定義

インスタンス変数は、インスタンスを生成した後からでも追加できます。

class Person:
    def __init__(self, name):
        self.name = name


p = Person('ムスカ')
# 動的にインスタンス変数を追加
p.age = 28

print(p.name)
print(p.age)

実行結果

ムスカ
28

Python では、このように後から簡単にインスタンス変数を追加できます。

クラス変数

クラス変数は、インスタンス化しなくても呼び出すことができる変数です。

定義

クラス変数を定義するには、クラス内で変数を定義します。

class クラス名:
    # クラス変数定義
    クラス変数名 = 値

呼び出し

クラス変数を呼び出すには、以下のように呼び出します。

クラス名.クラス変数名

サンプル

試しにクラス変数を定義して呼び出してみましょう!

class Test:
    # クラス変数の定義
    var = 'クラス変数'


# クラス変数の呼び出し
print(Test.var)

実行結果

クラス変数
クラス変数はインスタンスからでも呼び出せますが、紛らわしいのでクラスから呼び出すようにしましょう!

同名の変数が定義されている場合

同名のクラス変数とインスタンス変数が定義されている場合、インスタンスからはインスタンス変数が呼び出されます。

class Test:
    var = 'クラス変数'

    def __init__(self):
        self.var = 'インスタンス変数'


t = Test()
print(t.var)

実行結果

インスタンス変数

クラス内に定義した関数(メソッド)

クラス内に定義した関数のことを「メソッド」と呼びます。メソッドには、3つの種類があるので 1つずつ見ていきましょう!

インスタンスメソッド

インスタンスメソッドは、インスタンス化しないと呼び出せないメソッドです。

定義方法

インスタンスメソッドは、self を引数に持った関数を定義すれば良いだけです。

class クラス名:

    # 引数無し
    def メソッド名(self):
        # 何らかの処理

    # 引数有り
    def メソッド名(self, 引数1, 引数2, ..., 引数N):
        # 何らかの処理

呼び出し方法

インスタンスメソッドを呼び出すには、以下のようにします。

# 引数無し
インスタンス名.インスタンスメソッド名()

# 引数有り
インスタンス名.インスタンスメソッド名(値1, 値2, ..., 値N)

サンプル

試しにインスタンスメソッドを定義して使ってみましょう!

class Cat:

    # インスタンスメソッド
    def cry(self):
        print('にゃ〜')


tama = Cat()
tama.cry()

実行結果

にゃ〜

selfを使ってインスタンスにアクセスする

self を使ってインスタンスにアクセスすることで、自身のインスタンス変数やインスタンスメソッドを呼び出すことができます。

class Animal:

    def __init__(self, name, sound):
        # インスタンス変数
        self.name = name    # 名前
        self.sound = sound  # 鳴き声

    def cry(self):
        # インスタンス変数の呼び出し
        print(self.sound)

    def output(self):
        # インスタンス変数の呼び出し
        print(self.name)
        # インスタンスメソッドの呼び出し
        self.cry()



cat = Animal('たま', 'にゃ〜')
cat.output()

実行結果

たま
にゃ〜

このように、self を使うことで自身のインスタンス変数やメソッドを呼び出すことができます。

クラスメソッド

クラスメソッドは、インスタンス化しなくても呼び出せるメソッドです。
self を使ったインスタンスへのアクセスはできません。

定義

クラスメソッドは、以下のように @classmethodデコレータ を使って定義します。
引数には cls を必ず定義する必要があります。

class クラス名:

    # 引数無し
    @classmethod
    def クラスメソッド名(cls):
        # 何らかの処理

    # 引数有り
    @classmethod
    def クラスメソッド名(cls, 引数名1, 引数名2, ..., 引数名N):
        # 何らかの処理

呼び出し

クラスメソッドを呼び出すには、以下のようにします。

# 引数無し
クラス名.クラスメソッド名()

# 引数有り
クラス名.クラスメソッド名(値1, 値2, ..., 値N)

サンプル

cls にアクセスすることで自らのクラスを呼び出すことができます。

class Point:
    # クラス変数
    num = 10

    def __init__(self, x, y):
        self.x = x
        self.y = y

    # クラスメソッド
    @classmethod
    def class_method(cls):
        # Point(1, Point.num)と同等
        return cls(1, cls.num)

    # 出力
    def output(self):
        print(f'x: {self.x}, y: {self.y}')


# クラスメソッドの呼び出し
p = Point.class_method()
p.output()
print(type(p))

実行結果

x: 1, y: 10
<class '__main__.Point'>

スタティックメソッド

スタティックメソッドは、インスタンス化しなくても呼び出せるメソッドです。
selfcls にはアクセスすることができません。

定義方法

スタティックメソッドは、以下のように @staticmethodデコレータ を使って定義します。引数に selfcls は使えません。

class クラス名:

    # 引数無し
    @staticmethod
    def メソッド名():
        # 何らかの処理

    # 引数有り
    @staticmethod
    def メソッド名(引数名1, 引数名2, ..., 引数名N):
        # 何らかの処理

呼び出し方法

スタティックメソッドを呼び出すには、以下のようにします。

# 引数無し
クラス名.スタティックメソッド名()

# 引数有り
クラス名.スタティックメソッド名(値1, 値2, ..., 値N)

サンプル

試しにスタティックメソッドを定義して使ってみましょう!
通常の関数をクラス内に定義できるイメージです。

class Test:

    @staticmethod
    def s_method():
        print('スタティックメソッドです!')


# スタティックメソッドの呼び出し
Test.s_method()

実行結果

スタティックメソッドです!

属性(attribute)

属性とは、a.bb のことを言います。. で繋げて呼び出されるものは全て属性です。具体的に言えば、インスタンス変数やメソッドなどは属性です。

dir() を使うことでオブジェクトが持つ属性を確認することができます。

class Test:
    # クラス変数
    hoge = 'hoge'

    def __init__(self):
         # インスタンス変数
         self.moge = 'moge'

    # インスタンスメソッド
    def method(self):
         print(self.moge)


# クラスの属性の確認
print(dir(Test))

# インスタンスの属性の確認
t = Test()
print(dir(t))

実行結果

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'hoge', 'method']
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'hoge', 'method', 'moge']

大量にある '__メソッド名__' は、特殊メソッドと呼ばれるメソッドです。コンストラクタやデストラクタもこれに含まれます。

実行結果を右にスクロールして最後の方を見て下さい。
どちらの出力結果にも Testクラス の属性が追加されているのがわかります。

moge はインスタンス変数なのでインスタンス化しないと生成されません。

特殊メソッドには 演算子をオーバーロードできるものも用意されています。詳しくは以下の記事を参照してください。

演算子をオーバーロードする特殊メソッドの使い方

継承

クラスは継承することができます。

継承とは「あるクラスから派生したクラスを定義すること」を言います。継承させることで親の性質や機能を引き継ぎ、さらに拡張・追加することができます。

例えば、文字列を扱いたいけど通常の str型 では物足りないなっと思った時に、str型 を継承した新しいクラスを定義し、自分が欲しい機能を追加したりできます。

# クラス名の後ろに(継承する型名)を記述する
class MyStr(str):

    def 追加するメソッド(self):
        print('追加メソッド')


ms =  MyStr('ABC')
ms.追加するメソッド()

# もちろん、strのメソッドも使用可能
ms.index('B')

実行結果

追加メソッド

str型 に定義されているメソッドを拡張・変更することも可能です。

継承の使い方【派生クラスの定義】

合成と委譲

継承は使いこなすのが難しいので代わりに 合成と委譲 を使うことで より簡単に同じような処理を実装できます。

合成とは、使用したい機能を持つオブジェクトを属性として持たせることを言います。例えば、文字列のような機能を使いたいと思ったら文字列を属性に持たせます。

class MyStr():

    def __init__(self, s: str) -> None:
        self._s = s

移譲とは、合成で持たせた属性をメソッドから呼び出すことを言います。

class MyStr():

    def __init__(self, s: str):
        self._s = s

    # 委譲
    def count(self, char):
        return self._s.count(char)


ms = MyStr('ABCA')
print(ms.count('A'))

実行結果

2

継承を使わずとも合成と委譲を使うことで同様の処理を実装できました。

合成と委譲の使い方について解説

まとめ

この記事では、Pythonのクラスについて解説しました。

今回のおさらい

わからない箇所があったら記事を読み返してみましょう!

クラスの定義

class クラス名:

    # クラス変数
    クラス変数名 = 値
    
    # コンストラクタ
    def __init__(self, 引数名):
        # インスタンス変数
        self.インスタンス変数名 = 引数名

    # デストラクタ
    def __del__(self):
        なんらかの処理

    # メソッド
    def メソッド名(self):
        なんらかの処理

    # クラスメソッド
    @classmethod
    def クラスメソッド名(cls):
        なんらかの処理

    # スタティックメソッド
    @staticmethod
    def スタティックメソッド名():
        なんらかの処理

インスタンス化

# インスタンス化
インスタンス名 = クラス名()

# インスタンス変数にアクセス
インスタンス名.インスタンス変数名

# メソッドを使う
インスタンス名.メソッド名()

今回は覚える内容が多かったと思いますが、オブジェクト指向言語にとってクラスはとても重要な機能になります。何度も読み返してしっかりと覚えましょう!

それでは今回の内容はここまでです!ではまたどこかで〜( ・∀・)ノ