クラスとは、簡単に言いますと、変数と関数(クラス内の関数はメソッドと言います)の集まりです(丁寧に言いますと「オブジェクト指向とは?」という概念の説明になり、その説明で複雑になり、初心者にはわかりにくくなりますので、最初は「クラスとは変数とメソッドの集まり」と覚えておけばいいと思います)。
クラスを使う時は、基本的にインスタンス化して使います。
インスタンス化したものを「インスタンス」または「オブジェクト」と言います。
そのオブジェクトに対して何らかの操作をして使います。
簡単なクラスの例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# クラス名は大文字で始める class Test: # コンストラクタ(インスタンス化する時に呼び出されるメソッド)で引数をインスタンス変数に代入 # 引数のselfはクラスのインスタンス自身を表すもの # selfの引数がついているメソッドはインスタンスメソッド def __init__(self, name): # selfの引数がついている変数はインスタンス変数 # インスタンス変数はインスタンスメソッドの内で定義する self.name = name print("コンストラクタ") # インスタンスメソッド def get_name(self): return self.name # インスタンス化 a = Test("ライブインホープ") # メソッド実行 print(a.get_name()) |
結果
コンストラクタ
ライブインホープ
クラスの例2
C++によるプログラミング入門7のクラスを参考にさせていただきました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
class Rocket: def __init__(self, name, nenryo): self.name = name self.nenryo = nenryo self.sokudo = 0 def kasoku(self): if self.nenryo >= 2: self.nenryo -= 2 self.sokudo += 2 print(f"{self.name}:現在の燃料は{self.nenryo}です。") print(f"{self.name}:現在の速度は{self.sokudo}です。") print("--------") else: print(f"{self.name}:燃料切れです。加速できません。") print("--------") obj1 = Rocket("ロケット1号", 5) obj2 = Rocket("ロケット2号", 10) obj1.kasoku() obj2.kasoku() obj1.kasoku() obj2.kasoku() obj1.kasoku() obj2.kasoku() |
結果
ロケット1号:現在の燃料は3です。
ロケット1号:現在の速度は2です。
——–
ロケット2号:現在の燃料は8です。
ロケット2号:現在の速度は2です。
——–
ロケット1号:現在の燃料は1です。
ロケット1号:現在の速度は4です。
——–
ロケット2号:現在の燃料は6です。
ロケット2号:現在の速度は4です。
——–
ロケット1号:燃料切れです。加速できません。
——–
ロケット2号:現在の燃料は4です。
ロケット2号:現在の速度は6です。
——–
Rocketクラスから2つのインスタンスを生成して、それぞれのオブジェクトがkasokuメソッドを繰り返しているだけです。
クラスの例3
リストに4つのクラスのインスタンスを入れて、ループして、calc関数にオブジェクトなどを渡しています。4つのクラスはcalcという同じメソッド名を持っていますが、その中身は違うので、ポリモーフィズム(後述)感が出ます。
※Pythonは関数を引数にできますので、これは関数だけでもできますが、クラスの説明ということなのでご了承下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class Add: def calc(self, a, b): return a + b class Sub: def calc(self, a, b): return a - b class Mul: def calc(self, a, b): return a * b class Div: def calc(self, a, b): return a / b def calc(obj, a, b): return obj.calc(a, b) lists = [Add(), Sub(), Mul(), Div()] for obj in lists: print(calc(obj, 9, 3)) |
結果
12
6
27
3.0
クラスの例4
バトルゲームのような感じです。randomを使うとゲームっぽくなります。
Playerクラスで2つのインスタンスを作成し、Battleクラスのインスタンスの中で使用しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# random.randintを使うためのインポート import random class Player: def __init__(self, name, hp): self.name = name self.hp = hp def attack(self): # random.randint(a, b) はaからbまでの整数をランダムで返します return random.randint(0, self.hp) class Battle: def fight(self, p1, p2): while True: if self.result(p1, p2) == False: print("Game Over") break if self.result(p2, p1) == False: print("Game Over") break def result(self, a, b): a_attack = a.attack() b.hp -= a_attack print(f"{a.name}の攻撃:{a_attack}のダメージを与えた!") print(f"{b.name}の体力は{b.hp}になった!") if b.hp <= 0: print(f"{b.name}は死んだ!") return False else: return True p1 = Player("ライブ", 30) p2 = Player("ホープ", 50) b = Battle() b.fight(p1, p2) |
結果はランダムになります
ライブの攻撃:10のダメージを与えた!
ホープの体力は40になった!
ホープの攻撃:16のダメージを与えた!
ライブの体力は14になった!
ライブの攻撃:1のダメージを与えた!
ホープの体力は39になった!
ホープの攻撃:27のダメージを与えた!
ライブの体力は-13になった!
ライブは死んだ!
Game Over
クラス変数、インスタンス変数、ローカル変数
クラス変数はクラス共通で使用できる変数です。
インスタンス変数は特定のインスタンスのみで使える変数です。第一引数にselfのついたメソッド内で定義します。
メソッド内だけで使えるローカル変数は関数の時と同じ使い方です。
Javaとは違いprivateやprotectedがないです。アンダースコア(_)で始まる変数や関数は外から参照しないという慣習があり、アンダースコア2個(__)で始まる変数や関数は参照制限されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
class Test: # クラス変数(クラス共通の変数) c_var = 0 # コンストラクタ(インスタンスメソッド) def __init__(self,i_var): # クラス変数に1をプラス Test.c_var += 1 # インスタンス変数(インスタンス固有の変数) self.i_var = i_var # インスタンスメソッド def method1(self): # メソッドのローカル変数(メソッド内だけ使える変数) l_var3 = "l_var3" return f"クラス変数:{Test.c_var}/インスタンス変数:{self.i_var}/ローカル変数:{l_var3}" # クラス変数はインスタンス化しなくても参照できる print(Test.c_var) # インスタンス化 a = Test("変数1") print(a.method1()) # インスタンス化 b = Test("変数2") print(b.method1()) # インスタンス化 c = Test("変数3") print(c.method1()) # クラス変数はインスタンス化しなくても参照できる print(Test.c_var) |
結果
0
クラス変数:1/インスタンス変数:変数1/ローカル変数:l_var3
クラス変数:2/インスタンス変数:変数2/ローカル変数:l_var3
クラス変数:3/インスタンス変数:変数3/ローカル変数:l_var3
3
インスタンスメソッド、クラスメソッド、スタティックメソッド
インスタンスメソッドは第一引数にselfがあり、インスタンスから呼び出せるメソッド。
クラスメソッドは@classmethodという記述で、第一引数にclsがあるメソッド。
スタティックメソッドは@staticmethodという記述のあるメソッド。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
class Test: # クラス変数 name = "クラス変数" # コンストラクタ(インスタンスメソッド) def __init__(self): # インスタンス変数 self.val = "インスタンス変数" # インスタンスメソッド def instance_method(self): print(self.val) # クラスメソッド @classmethod def class_method(cls): print(cls.name) # スタティックメソッド @staticmethod def static_method(): print(Test.name) # インスタンスメソッドはインスタンス化しないと呼び出せない a = Test() a.instance_method() # クラスメソッドとスタティックメソッドはインスタンス化しなくても呼び出せる Test.class_method() Test.static_method() # クラスメソッドとスタティックメソッドはインスタンスからも呼び出せる a.class_method() a.static_method() |
結果
インスタンス変数
クラス変数
クラス変数
クラス変数
クラス変数
クラスメソッドとスタティックメソッドの使い分けは、スタティックメソッドはclsの引数がいらないので、クラスに依存しない処理の場合に使えばいいそうです。