【Python】型を定義する方法【class(クラス)の使い方】

Python

この記事では、Pythonのクラスを使って型を定義する方法を解説します。クラスは、オブジェクト指向言語の中核を担う機能なので、しっかりと覚えておきましょう!

クラスとは?

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

型ってなんだっけ?

『データの性質を定めて取り扱い方を定義したもの』です!

つまり、クラスを定義することで

そのデータがどのような性質を持ち、どのような取り扱われ方をするのか定義できる

ということです。

クラスの使い方

クラスは、以下のような流れで使われます。

クラスを使用する流れ

  1. クラスを定義する
  2. インスタンス化
  3. クラスの機能を呼び出す

それでは、この流れに沿って使い方を見ていきましょう!

1. クラスを定義する

クラスは、以下のように定義します。

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

クラス名の頭文字には大文字を使いましょう。
※ クラスの中の定義については追々見ていきます。

2. インスタンス化

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

インスタンスとは?

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

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

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

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

補足
  • 他の言語では、シングルトンと言ってインスタンスが1つしか生成できないクラスもあります。

3. クラスの機能を呼び出す

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

インスタンス名.変数名

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

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

補足:インスタンスについて

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

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

この例え話をコードとして表すと、以下のようになります。

# たい焼きクラス
class たい焼き:
    def __init__(self, 中身):
        self.中身 = 中身

# インスタンス生成
あんこたい焼き = たい焼き('あんこ')
カスタードたい焼き = たい焼き('カスタード')

print(あんこたい焼き.中身)
# あんこ

print(カスタードたい焼き.中身)
# カスタード

※ 今回はわかりやすさを重視して、クラス名や変数名を日本語で記述しました。

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

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

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

定義方法

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

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

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

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

呼び出し方法

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

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

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

サンプル

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

class Person:
    # コンストラクタ
    def __init__(self, name):
        # インスタンス変数の定義(後述)
        self.name = name


# Personクラスからmikeというインスタンス生成
mike = Person('マイク')

# インスタンス変数の出力
print(mike.name)

実行結果

マイク

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

デストラクタ

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

定義方法

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

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

サンプル

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

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


t = Test()

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

実行結果

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

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

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>

selfとtestインスタンスを出力してみましたが、二つとも全く同じ値が出力がされました。つまり、selfはtestインスタンスと同等ということがわかります。

クラスに定義できる変数

クラスには以下の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


zero = Person('綾波レイ', 14, '女')
print(f'名前: {zero.name}, 年齢: {zero.age}, 性別: {zero.gender}')

first = Person('碇シンジ', 14, '男')
print(f'名前: {first.name}, 年齢: {first.age}, 性別: {first.gender}')

実行結果

名前: 綾波レイ, 年齢: 14, 性別: 女
名前: 碇シンジ, 年齢: 14, 性別: 男

動的な定義

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

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つの種類があります。

メソッドの種類

  • インスタンスメソッド
  • クラスメソッド
  • スタティックメソッド

インスタンスメソッド

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

定義方法

インスタンスメソッドは、以下のように定義します。必ず引数に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'>

スタティックメソッド

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

定義方法

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

class クラス名:

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

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

呼び出し方法

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

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

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

サンプル

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

class Test:

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


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

実行結果

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

属性(attribute)

属性とは、オブジェクトが持つ変数やメソッドのことを言います。

属性を確認する

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はインスタンス変数なので、インスタンス化しないと生成されません。

カプセル化

外部から属性を隠蔽することをカプセル化と言います。外部からの干渉を未然に防ぐことで予期せぬ値で書き換えたりできなくします。

また、外部から呼び出す必要のない変数やメソッドを秘匿することで、直感的に使いやすいクラスを作成することができます。

それでは

  • プライベートな変数の定義方法
  • プライベートなメソッドの定義方法

を見ていきましょう!

プライベートな変数の定義方法

プライベートな変数を定義するには「_(アンダーバー)」を使います。

定義方法

識別子の先頭に「_(アンダーバー)」を2つ付けることで定義できます。

class クラス名:
    # クラス変数
    __変数名 = データ
    def __init__(self):
        # インスタンス変数
        self.__変数名 = データ

サンプル

内部からは呼び出すことができます。

class Cat:
    # クラス変数
    __sound = 'にゃ〜'
    def __init__(self, name):
        # インスタンス変数
        self.__name = name

    def output(self):
        print(f'名前: {self.__name}')
        print(f'鳴き声: {self.__sound}')


shamisen = Cat('シャミセン')
shamisen.output()

# 外部から呼び出そうとするとエラー発生
print(shamisen.__name)

実行結果

名前: シャミセン
鳴き声: にゃ〜
AttributeError: 'Cat' object has no attribute '__name'

プライベートなメソッドの定義方法

メソッドも「_(アンダーバー)」を使って定義できます。

定義方法

変数と同様にメソッド名の先頭に「_(アンダーバー)」を2つ付けます。

変数と違うのは、末尾に「_(アンダーバー)」を2つ付けてはいけないことです。特殊メソッドとしてみなされてしまいます。

class クラス名:

    def __メソッド名(self):
        # 何かしら処理

サンプル

変数と同様に内部からなら呼び出せます。

class Cat:
    # クラス変数
    __sound = 'にゃ〜'
    def __init__(self, name):
        # インスタンス変数
        self.__name = name

    def __output_name(self):
        print(f'名前: {self.__name}')

    def __output_sound(self):
        print(f'鳴き声: {self.__sound}')

    def output(self):
        self.__output_name()
        self.__output_sound()


shamisen = Cat('シャミセン')
shamisen.output()

# エラー
shamisen.__output_name()

実行結果

名前: シャミセン
鳴き声: にゃ〜
AttributeError: 'Cat' object has no attribute '__output_name'

補足: マングリング

Pythonでは、本当の意味でのプライベートな属性を定義することができません。先ほど定義した属性は正確にはプライベートに見える属性です。「_(アンダーバー)」が2つ付けられた識別子は、マングリングによって「_クラス名__識別子」という名前に置換されます。

例えば、以下のコードを見てください。「_(アンダーバー)」が2つ付けられている属性が普通に呼び出せてしまっています。


class TestClass:
    __クラス変数 = 'クラス変数'
    def __init__(self):
        self.__インスタンス変数 = 'インスタンス変数'

    def __メソッド(self):
        print('メソッド')


c = TestClass()

# クラス変数へのアクセス
print(TestClass._TestClass__クラス変数)

# インスタンス変数へのアクセス
print(c._TestClass__インスタンス変数)

# メソッドへのアクセス
c._TestClass__メソッド()

# 書き換えることもできる
c._TestClass__インスタンス変数 = 'インスタンス変数です'
print(c._TestClass__インスタンス変数)

実行結果

クラス変数
インスタンス変数
メソッド
インスタンス変数です

このように、Pythonでは本当の意味でのプライベートな属性を定義することはできません。

まとめ

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

今回のおさらい

クラスの使い方

class クラス名:

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

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

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

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

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

インスタンス化

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

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

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

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

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

タイトルとURLをコピーしました