概要
Pythonのクラス定義方法、属性とメソッド、インスタンス操作などをまとめた。
クラスの定義
Pythonでクラスを定義するには、以下のようにclassキーワードを使用する。
class Human:
pass
この例ではHumanクラスを定義している。
passはまだ何もしないという意味。
属性とメソッド
クラスの属性(フィールド)とメソッドは以下のように記述する。
class Human:
def __init__(self, name, age):
# 属性
self.name = name
self.age = age
# あいさつメソッド
def introduce_myself(self):
print(f"わたしの名前は{self.name}で年齢は{self.age}です。")
__init__を使用して、そのクラスに保持する属性を定義することができる。
selfはクラスメソッドの第一引数に定義するのが慣習と思った方がいい。
インスタンスの作成と使用
以下のようにHuman(人間)クラスをインスタンス化して使用する。
tanaka = Human("田中太郎", 24)
yamada = Human("山田次郎", 23)
print(tanaka.name) # 田中太郎
print(tanaka.age) # 24
tanaka.introduce_myself() # わたしの名前は田中太郎で年齢は24です。
print(yamada.name) # 山田次郎
print(yamada.age) # 23
yamada.introduce_myself() # わたしの名前は山田次郎で年齢は23です。
Humanはコンストラクタとしてnameとageを設定する。
引数に何も設定していない場合、エラーになる。
継承
継承することにより、親クラスの属性やメソッドを引き継ぐことが可能になる。
Pythonで継承を定義するためには、以下のように記述する。
class 子クラス(親クラス):
pass
以下はHuman(人間)を継承してサッカー選手、野球選手のクラスを作成する方法になる。
# Humanを継承した野球選手クラス
class BaseBallPlayer(Human):
# あいさつメソッドのオーバーライド
def introduce_myself(self):
super().introduce_myself()
print("野球選手でもあります。")
# BaseBallPlayer独自のメソッド
def throw_ball(self):
print("ボールを投げます。")
# Humanを継承サッカー選手クラス
class FootballPlayer(Human):
# あいさつメソッドのオーバーライド
def introduce_myself(self):
super().introduce_myself()
print("サッカー選手でもあります。")
# FootballPlayer独自のメソッド
def kick_ball(self):
print("ボールを蹴ります。")
「super().introduce_myself()」と記述することで、親クラスのメソッドを呼び出すことができる。
また、親クラスのメソッドを呼び出したのちに、print関数によりメッセージを出力している。
継承したクラスをインスタンス化して使用するには以下のように記述する。
tanaka = BaseBallPlayer("田中太郎", 24)
yamada = FootballPlayer("山田次郎", 23)
tanaka.introduce_myself()
tanaka.throw_ball()
yamada.introduce_myself()
yamada.kick_ball()
# ------------------------------------
# 出力
#わたしの名前は田中太郎で年齢は24です。
#野球選手でもあります。
#ボールを投げます。
#わたしの名前は山田次郎で年齢は23です。
#サッカー選手でもあります。
#ボールを蹴ります。
クラス変数とインスタンス変数
Pythonのクラスにはクラス変数とインスタンス変数が存在する。
クラス変数にはクラスで共通の値を保持することができる。
一方で、インスタンス変数はインスタンス毎に独自の値を保持することができる。
# クラス変数とインスタンス変数
class Dog:
type = "動物" # クラス変数
def __init__(self, name):
self.name = name # インスタンス変数
class直下の属性に定義した変数はクラス変数となり、クラス内で共有されている。
コンストラクタで作成された変数はインスタンス変数となり、作成したインスタンスで参照が可能になる。
dog1 = Dog("テリー")
dog2 = Dog("ラッシュ")
print(dog1.type) # 動物
print(dog2.type) # 動物
print(dog1.name) # テリー
print(dog2.name) # ラッシュ
print(Dog.type) # 動物 ※クラス名.変数名の形式でも参照可能
Dog.type = "アニマル" # クラス変数の変更
print(dog1.type) # アニマル
print(dog2.type) # アニマル
クラス変数を修正した場合、そのクラスを使用しているインスタンスに影響があるので注意が必要。
クラスメソッドとスタティックメソッド
Pythonのクラスでは、クラスメソッドとスタティックメソッドを定義できる。
class CalcUtil:
value = 0
@classmethod
def increment(cls):
""" クラス変数を操作する """
cls.value += 1
return f"CalcUtilのvalue:{cls.value}"
@staticmethod
def calc_price(total, member):
""" 割り勘して1人あたりの金額を出す """
return total // member
print(CalcUtil.increment()) # CalcUtilのvalue:1
print(CalcUtil.calc_price(1000, 2)) # 500
どちらもインスタンスを作成せずとも参照が可能となる。
そのため、ユーティリティクラスなどで使用される。
クラス変数にアクセスする必要がない場合、基本的にはスタティックメソッドの方を使用する。
※引数のclsは自クラスということ。selfのときと同様に慣習と思った方がいい。
カプセル化
クラスの値に対して参照の制限をかけることができる。
属性に対してアンダースコアを2つ(__)つけると、private状態になり、外部から参照できなくなる。
privateな属性を操作するためには、ゲッターとセッターの定義が必要になる。
class Human:
type = "ヒト" # public
__secret = "秘密" # private
def __init__(self, name, age, tell):
self.name = name # public
self.age = age # public
self.__tell = tell # private
# クラス変数__secretのゲッター
def get_secret(self):
return Human.__secret
# インスタンス変数__tellのゲッター
def get_tell(self):
return self.__tell
# インスタンス変数__tellのセッター
def set_tell(self, tell):
self.__tell = tell
privateな属性を操作するためには以下のように記述する。
※インスタンス変数.private属性名とするとAttributeErrorになるので注意。
satou = Human("佐藤", 30, "090-XXXX-XXXX")
print(satou.name) # 佐藤
print(satou.age) # 30
print(satou.type) # ヒト
#print(satou.__secret) # AttributeError: 'Human' object has no attribute '__secret'
#print(satou.__tell) # AttributeError: 'Human' object has no attribute '__secret'
print(satou.get_secret()) # 秘密
print(satou.get_tell()) # 090-XXXX-XXXX
satou.set_tell("080-XXXX-XXXX")
print(satou.get_tell()) # 080-XXXX-XXXX
プロパティ
クラスのメソッドにpropertyデコレータをつけると、メソッドを属性のように扱える。
class Human:
def __init__(self, name, age):
self.name = name
self.age = age
@property
def myself(self):
return f"わたしの名前は{self.name}で年齢は{self.age}です。"
出力結果
tanaka = Human("田中太郎", 24)
print(tanaka.name) # 田中太郎
print(tanaka.age) # 24
print(tanaka.myself) # わたしの名前は田中太郎で年齢は24です。