具体例で学ぶ、Pythonのclassの使い方
Pythonではclassを活用してプログラミングができます。
しかしclassの概念は初学者には理解が難しく、
・何のためのものかイメージしづらい
・どういうときに使いたいものなのかイメージしづらい
と感じている方も多いのではないでしょうか。
そこで本記事では、
・クラスとはどういうものか
・どういうときに使うものなのか
について説明し、具体的な使い方をコードを交えて解説します。
少しでもイメージしやすいように、具体的な使用イメージがわくようなコード例、丁寧なコメントによる、初学者でも理解しながら実行できるコード例を心がけています。
ぜひ手元で実行しながら、できれば少しずつでもコードを改造しながらお読みいただけますと幸いです。
Pythonについてはこちらもどうぞ
classとは
classを使用すると、関数を定義するときのように複数の処理や値をまとめておくことができます。
classからは「インスタンス」というものが作成でき、インスタンスにはデータを保持させておくことができたり(属性)、関数のように処理をまとめておくことができたり(メソッド)します。
このように、「1つのもの(オブジェクト)に情報や処理をひも付けて管理できる」のがclassです。
例えば、「人間」というclassがあるとしましょう。
人間classをひな形として1人1人の個人が作られます。
この人間インスタンスにはそれぞれ共通する
・属性:名前や年齢、性別、お腹の空き具合
・メソッド:食べる、寝る
などの項目が設定されている、というイメージです。
classを作成しておくことで、似たようなインスタンスを自由に生み出すことができます。
そのため、classはインスタンスを作成するための「ひな形」「設計図」「工場」などとも言われます。
classの「継承」という機能を使うことで、とあるclassから派生したclassを作ることも簡単にできます。
例えば、「人間」classを拡張した「大人」classでは、「人間」classで設定した属性、メソッドに加えて
・属性:年収、仕事、趣味、好きなもの
・メソッド:歩く、走る、話す、働く
などを追加することができます。
このように、classを活用すれば
・似たようなコードを繰り返し書く必要がなくなる
・コードを再利用しやすい
・機能を拡張しやすい
という恩恵が得られます。
classはどんなときに必要なのか
classはPythonを始めたばかりのころはあまりお世話にならないかもしれません。
そのため
「classを使わなくてもプログラミングできてる。classって何に使うんだろう…。」
と疑問に思うことでしょう。
classは「対象となる物」を作成し、対象物に関する情報や動きをひとまとめにして使い回すことができます。
classが必要になる場面としてイメージしやすいのはゲーム制作です。
ゲームでは登場人物や敵キャラ、使用する道具などさまざまなものが登場します。
これら全て、固有の情報や動き方、使い方が備わっているため、それぞれの共通部分をclassにすることでコーディングが効率的になります。
このように、多様なものをたくさん用意する必要がある場合にclassが威力を発揮します。
そのため、ゲーム以外にも、何かしらの対象物を作成して扱う必要があればclassを活用できるでしょう。
また、Pythonでいつもお世話になっているrandomやpandasなどといったモジュールでもクラスが活用されています。大規模な開発では、classを使用できるに越したことはないのです。
Pythonにおけるclassの具体的な使い方
それでは、具体例を元にPythonでのclassの使い方を見ていきましょう。
今回はゲームの登場キャラクターのひな形になるclassを作成してみます。
キャラクター共通の機能を持ったCharacterクラス、Characterクラスに追加機能を付けた「村人」(Villager)、「自キャラ」(Hiro)のclassを作成してみます。
classの作り方
まずはCharacterクラスを作成します。
属性やメソッドを設定していないclassは以下のようになります。
なお、class名は大文字で開始し、単語を繋げるときはCharacterClassのように各単語の頭文字を大文字にします。
class Character: # classを定義する pass # デモのため、何もしない
これでCharacterクラスの定義ができました。
実際にCharacterインスタンスを作成するには
chara1 = Character() # chara1変数にCharacterインスタンスを作成
とclassを変数に代入すればOKです。
classの属性
キャラクターには「名前」(name)、「年齢」(age)、「性別」(sex)という属性を付けることにします。
属性は以下のように設定できます。
chara1.name = 'Kazuma' # chara1インスタンスのname属性の値を’Kazuma’に設定 chara1.age = 16 # chara1インスタンスのage属性の値を16に設定 chara1.sex = 'male' # chara1インスタンスのsex属性の値を’male’に設定
chara1.nameという変数に値を代入したようなものなので、以下のように値を使用することもできます。
print(chara1.name)
出力
Kazuma
別のインスタンスには別の値を設定できます。
chara2 = Character() # chara2変数にCharacterインスタンスを作成 chara2.name = 'Megumi' # chara1とは別の値を設定できる chara2.age = 13 chara2.sex = 'female' print(chara2.name)
出力
Megumi
ここまでではclassのありがたみはまだ感じられませんが、これから少しずつclassの利点が見えてきます。
classのメソッド
classにはメソッドを定義することもできます。
関数と同じくdef文を使用しますが、第1引数に「self」というオブジェクトを指定しておく点が特徴的です。
selfはその名の通り「メソッドを呼び出したインスタンス自身」を指します。
インスタンスを表す変数名はさまざまですが、それらを共通してselfとして表現しています。
「メソッドの引数に自分自身を入れることで、自分自身に設定されている属性の値を利用できる」というイメージです。
実際の使い方を見た方が早いですので、以下で「名前」(name)、「年齢」(age)、「性別」(sex)という属性を設定するメソッド(set_data(self, name, age, sex))、これらの情報をprintするメソッド(print_data(self))を設定してみましょう。
class Character: def set_data(self, set_name, set_age, set_sex): # 属性に値を一括で設定するメソッドを定義 self.name = set_name # selfには実際にはインスタンスが入る。 self.age = set_age # 属性の説明時に各属性に値を設定したのと同じこと。 self.sex = set_sex def print_data(self): print("私は{}。{}歳。{}です。".format(self.name, self.age, self.sex)) # 各属性の値をprint。
これらのメソッドを使用すれば、属性の説明の例で見たような手間をかけず、一括で必要な属性に値を設定できます。
なお、メソッドを実行する際にはselfを引数に指定せず、第2引数から指定します。
chara3 = Character() # 新しいインスタンスを作成 chara3.set_data('Kazuma', 16, 'male') # 一括で属性に値を設定
def set_data(self, set_name, set_age, set_sex): 内でselfにメソッドを呼び出したインスタンス自身(chara3)が代入されて self = chara3 となっています。
後の引数は関数と同様にそれぞれの変数に代入され、
self.name = set_name self.age = set_age self.sex = set_sex
が
chara3.name = 'Kazuma' chara3.age = 16 chara3.sex = 'male'
となっているわけです。
もう1つのメソッドを実行すると
chara3.print_data()
出力
私はKazuma。16歳。maleです。
となり、しっかりと属性が設定され、呼び出しもできることが確認できます。
なお、属性から直接値を呼び出すこともできます。
print(chara3.name)
出力
Kazuma
classのインスタンスを作成する際に呼び出されるメソッド
各インスタンスそれぞれに属性を設定する機会は多く、いちいち設定するのも面倒です。
そんな面倒さを解消できるように、classにはインスタンス作成時に自動で呼び出されるメソッド(__init__())
を定義することができます。
このメソッドは「コンストラクタ」と呼ばれます。
使い方は以下の通りです。
以下コードはメソッドの説明で定義したset_dataメソッドを__init__
に変更しただけのものです。
class Character: def __init__(self, name, age, sex): # コンストラクタでインスタンスを初期化 self.name = name self.age = age self.sex = sex def print_data(self): print("私は{}。{}歳。{}です。".format(self.name, self.age, self.sex))
__init__()
の引数は以下のようにインスタンス作成時に指定します。
chara4 = Character('Kazuma', 16, 'male') # インスタンス作成時にコンストラクタが呼び出される chara4.print_data()
出力
私はKazuma。16歳。maleです。
継承
classの便利な点はコードの使い回しがしやすい点、機能拡張がしやすい点です。
「継承」という機能を利用することで、他で作成したclassのメソッドや値を受け継ぎつつ、メソッド等を編集、追加できます。
定義するclass名の後ろに継承したいclass名を()内に指定すればOKです。
まずは村人(Villager)classを作成してみましょう。
村人にはCharacterクラスの機能に加え、台詞(line)を属性として持ち、台詞を話すspeak()メソッドも定義します。
class Villager(Character): # Characterクラスを継承 def __init__(self, name, age, sex, line): # コンストラクタを拡張 super().__init__(name, age, sex) # super()で継承元のクラスを呼び出せる self.line = line # 台詞を設定 def speak(self): # 台詞を話すメソッドを定義 print("{}「{}」".format(self.name, self.line))
Villagerクラスでは、Characterクラスのコンストラクタに台詞の設定も追加しています。
このように、super()で継承元のクラスを呼び出せます。
インスタンスを作成してみると
villager1 = Villager("apple seller", 35, "male", "おう!リンゴでもどうだい?") # インスタンス作成時、属性に値を設定 villager1.speak() # 台詞を話すメソッド
出力
apple seller「おう!リンゴでもどうだい?」
また、Characterクラスを継承しているので、Villagersクラスで定義していないprint_data()メソッドも呼び出せます。
villager1.print_data()
出力
私はapple seller。35歳。maleです。
これで村人を大量生産できますね。
同様に、自キャラ(Hiro)classも作成してみましょう。
自キャラにはCharacterクラスの機能に加え、体力(hp)と経験値(ex)、魔力(mp)を属性として持たせます。
また、魔力に応じて体力を回復するheal()メソッドも定義します。
class Hiro(Character): # Characterクラスを継承 def __init__(self, name, age, sex, hp, ex, mp): # コンストラクタを拡張 super().__init__(name, age, sex) # super()で継承元のクラスを呼び出せる self.hp = hp # 体力を設定 self.ex = ex # 経験値を設定 self.mp = mp # 魔力を設定 def heal(self): # 魔力に応じて体力を回復するメソッド self.hp += self.mp # 体力を魔力分回復 print("HPが{}回復".format(self.mp)) # 回復量を表示 print("現在のHP:{}".format(self.hp)) # 回復後の体力を表示
インスタンスを作成してみると
hiro1 = Hiro('Kazuma', 16, 'male', 100, 200, 30) hiro1.heal() # 魔力分の体力を回復するメソッド
出力
HPが30回復 現在のHP:130 hiro1.print_data() # Hiroクラスで設定していないメソッドも、継承元から呼び出せる
出力
私はKazuma。16歳。maleです。
このように、共通する機能を持つclassを作成し、classを継承した新しいclassを作成することで機能を追加することができます。
classを使いこなして一段上のPython使いに
クラスの使い方を具体例とともに解説しました。
ここで解説した使い方はごく基本的なものですが、一歩を踏み出しておけば応用も理解しやすいでしょう。
小規模なソースコードでは活用するタイミングは無いかもしれませんが、classを使いこなせればできることが増えそうだと感じていただけたのではないでしょうか。
classは「習うより慣れろ」だと言われます。使えそうな場面を見つけ、classの使い方を調べながら積極的に活用してみましょう。
▽関連記事はこちら
▼キャパの公式Twitter・FacebookではITに関する情報を随時更新しています!