クラスの属性とメソッド:データと操作をまとめる#
はじめに#
前回の記事では、クラスの基本的な概念とオブジェクト指向プログラミングの考え方について学びました。クラスを使うと、データ(属性)と機能(メソッド)をひとまとめにできることがわかりました。今回は、クラスの属性とメソッドについてさらに詳しく掘り下げていきます。
クラスにはインスタンス属性とクラス属性、インスタンスメソッドとクラスメソッドという種類があります。これらの違いと使い方を理解することで、より柔軟で効率的なプログラムを書けるようになります。
インスタンス属性とクラス属性#
属性(データ)には、大きく分けて「インスタンス属性」と「クラス属性」の2種類があります。
インスタンス属性#
インスタンス属性は、各オブジェクト(インスタンス)がそれぞれ持つデータです。前回見た例では、商品の名前や価格、在庫数などがインスタンス属性でした。インスタンス属性は通常、__init__
メソッドの中でself.属性名 = 値
の形で定義します。
class Student:
def __init__(self, name, grade):
# インスタンス属性を定義
self.name = name # 名前
self.grade = grade # 学年
self.scores = [] # 成績リスト(空のリストで初期化)
# 学生オブジェクトを2つ作成
student1 = Student("田中", 2)
student2 = Student("佐藤", 3)
# それぞれの属性にアクセス
print(f"{student1.name}さんは{student1.grade}年生です。")
print(f"{student2.name}さんは{student2.grade}年生です。")
田中さんは2年生です。
佐藤さんは3年生です。
この例では、name
、grade
、scores
がインスタンス属性です。各学生オブジェクトは、自分自身の名前、学年、成績リストを持っています。一つのオブジェクトの属性を変更しても、他のオブジェクトには影響しません。
クラス属性#
クラス属性は、クラス全体で共有されるデータです。クラスの中で、メソッドの外側に定義します。すべてのオブジェクトで共通の値を使いたい場合に便利です。
class Student:
# クラス属性を定義
school_name = "山田学園"
def __init__(self, name, grade):
# インスタンス属性
self.name = name
self.grade = grade
def introduce(self):
print(f"私は{Student.school_name}の{self.name}です。{self.grade}年生です。")
# 学生オブジェクトを作成
student1 = Student("田中", 2)
student1.introduce()
# もう一人作成
student2 = Student("佐藤", 3)
student2.introduce()
# クラス属性にアクセス
print(f"学校名: {Student.school_name}")
私は山田学園の田中です。2年生です。
私は山田学園の佐藤です。3年生です。
学校名: 山田学園
この例では、school_name
がクラス属性です。学校名はすべての生徒で共通であるため、クラス属性として定義するのが適切です。クラス属性は、クラス名.属性名
の形でアクセスします。
インスタンス属性とクラス属性の違いを表にまとめると以下のようになります。
種類 | 定義場所 | アクセス方法 | 特徴 |
---|---|---|---|
インスタンス属性 | __init__ 内など | self.属性名 | オブジェクトごとに独立 |
クラス属性 | クラス内(メソッド外) | クラス名.属性名 | すべてのオブジェクトで共有 |
クラス属性はクラス内でself.属性名
でも参照できますが、いつでもクラス名.属性名
を使うことをおすすめします。self
を使うと、インスタンス属性とクラス属性が混同される可能性があります。クラス属性はクラス全体で共有されるため、クラス名.属性名
を使うことで、より明確に意図を示すことができます。
インスタンスメソッド・クラスメソッド・スタティックメソッド#
メソッドにも、いくつかの種類があります。主なものは「インスタンスメソッド」と「クラスメソッド」「スタティックメソッド」です。
インスタンスメソッド#
これまで見てきた通常のメソッドは「インスタンスメソッド」です。最初の引数にself
を取り、特定のオブジェクトに対して操作を行います。
class Circle:
def __init__(self, radius):
self.radius = radius
# インスタンスメソッド
def calculate_area(self):
return 3.14 * self.radius ** 2
# インスタンスメソッド
def calculate_circumference(self):
return 2 * 3.14 * self.radius
# 円のオブジェクトを作成
circle1 = Circle(5)
circle2 = Circle(7)
# メソッドを呼び出す
area1 = circle1.calculate_area()
area2 = circle2.calculate_area()
print(f"半径5cmの円の面積: {area1:.2f}平方cm")
print(f"半径7cmの円の面積: {area2:.2f}平方cm")
半径5cmの円の面積: 78.50平方cm
半径7cmの円の面積: 153.86平方cm
クラスメソッド#
クラスメソッドは、クラス全体に関わる操作を行うためのメソッドです。@classmethod
というデコレータを使って定義し、最初の引数にcls
(クラス自身)を取ります。クラスメソッドは、クラス名.メソッド名
の形で呼び出せます。
デコレータはメソッドなどに追加の処理を付与するための構文です。ここでは、メソッドの前に書く@
から始まる特別なコードということだけ覚えておきましょう。
class Student:
# クラス属性
school_name = "山田学園"
def __init__(self, name, grade):
self.name = name
self.grade = grade
# インスタンスメソッド
def introduce(self):
print(f"私は{self.school_name}の{self.name}です。{self.grade}年生です。")
# クラスメソッド
@classmethod
def change_school_name(cls, new_name):
# クラスメソッドではクラス属性は cls.school_name でアクセスできる
cls.school_name = new_name # Student.school_name = new_name と同じ
print(f"学校名を{cls.school_name}に変更しました。")
# まずはインスタンスを作る
student1 = Student("田中", 2)
student2 = Student("佐藤", 3)
# インスタンスメソッドを呼び出す
student1.introduce()
student2.introduce()
# クラスメソッドを呼び出す
Student.change_school_name("鈴木学園")
# 変更後のクラス属性はすべてのオブジェクトに影響する
student1.introduce()
student2.introduce()
私は山田学園の田中です。2年生です。
私は山田学園の佐藤です。3年生です。
学校名を鈴木学園に変更しました。
私は鈴木学園の田中です。2年生です。
私は鈴木学園の佐藤です。3年生です。
この例では、change_school_name
がクラスメソッドです。クラス属性であるschool_name
を変更・取得するために使われています。クラスメソッドはクラスに関連する操作に使用し、cls
を通じてクラス自体にアクセスします。
スタティックメソッド#
スタティックメソッドは、クラスやオブジェクトに関連しますが、クラス属性やインスタンス属性にアクセスする必要がない場合に使います。@staticmethod
デコレータを使って定義し、特別な最初の引数(self
やcls
)は必要ありません。
class MathHelper:
# クラス属性
pi = 3.14159
# スタティックメソッド
@staticmethod
def is_even(number):
return number % 2 == 0
# スタティックメソッド
@staticmethod
def absolute(number):
if number < 0:
return -number
return number
# インスタンスメソッド
def calculate_circle_area(self, radius):
return MathHelper.pi * radius ** 2
# クラスメソッド
@classmethod
def get_pi(cls):
return cls.pi
# スタティックメソッドはクラス名から直接呼び出せる
print(f"10は偶数ですか?: {MathHelper.is_even(10)}")
print(f"7は偶数ですか?: {MathHelper.is_even(7)}")
print(f"-5の絶対値: {MathHelper.absolute(-5)}")
# インスタンスを作成
math_helper = MathHelper()
# インスタンスメソッドを呼び出す
area = math_helper.calculate_circle_area(5)
print(f"半径5の円の面積: {area:.2f}")
# クラスメソッドを呼び出す
print(f"円周率: {MathHelper.get_pi()}")
10は偶数ですか?: True
7は偶数ですか?: False
-5の絶対値: 5
半径5の円の面積: 78.54
円周率: 3.14159
この例では、is_even
とabsolute
がスタティックメソッドです。これらのメソッドは、クラスやオブジェクトの状態に依存せず、単に引数に対して計算を行うだけです。
3種類のメソッドの違いを表にまとめると以下のようになります。
種類 | 定義方法 | 第一引数 | 特徴 |
---|---|---|---|
インスタンスメソッド | 通常の定義 | self (インスタンス) | インスタンス属性にアクセス可能 |
クラスメソッド | @classmethod | cls (クラス) | クラス属性にアクセス可能 |
スタティックメソッド | @staticmethod | なし(通常の引数) | クラス/インスタンス属性にはアクセスしない |
まとめ#
この記事では、クラスの属性とメソッドについて詳しく学びました。
- 属性の種類:
- インスタンス属性:各オブジェクトが独自に持つデータ
- クラス属性:クラス全体で共有されるデータ
- メソッドの種類:
- インスタンスメソッド:
self
を使って特定のオブジェクトに対して操作を行う - クラスメソッド:
@classmethod
デコレータとcls
引数を使い、クラス全体に関わる操作を行う - スタティックメソッド:
@staticmethod
デコレータを使い、クラスやオブジェクトの状態に依存しない操作を行う
- インスタンスメソッド:
これらの概念を理解し使いこなすことで、より整理されたクラス設計ができるようになります。