class(クラス定義)
このページでは豊富な例を用いてPythonのclass(クラス定義)の基本的な使い方を学ぶことができます。
classはPythonでクラスを定義するために使用される構文です。
クラスはオブジェクトの型を定義し、データ属性やメソッドを定義することで一定の振る舞いをある程度保証することができます。
クラスの命名はパスカルケースが推奨されています。
(大文字から始まり、続く単語は大文字から始まる。別名:アッパーキャメルケース)
注意
このページではクラスの基礎的な定義・使用方法について解説します。
カプセル化やポリモーフィズムといった概念に関しては解説していませんのでご注意ください。
TL;DR
クラスの定義・インスタンス化
# シンプルなクラス定義
class Person:
pass
# インスタンス化
person1 = Person()
# インスタンスの情報
print(person1)
==> <{環境により異なる文字列}.Person object at {オブジェクト識別値}>
print(type(person1))
==> <class '{環境により異なる文字列}.Person'>
print(vars(person1))
==> {}
# インスタンスの判定
print(type(person1) is Person)
==> True
print(type(person1) == Person)
==> True
print(isinstance(person1, Person))
==> True
# 異なるクラスの定義
class Language:
pass
class Animal:
pass
# インスタンス化
language1 = Language()
language2 = Language()
language3 = language1
animal1 = Animal()
# インスタンスの判定
# 型は同じでも異なるオブジェクトである
print(language1 == language2)
==> False
# language3はlanguage1を参照している
print(language1 == language3)
==> True
# オブジェクトは異なっても型は同じである
print(type(language1) == type(language2))
==> True
# language1はLanguageクラスのインスタンスなのでFalse
print(isinstance(language1, Animal))
==> False
# すべてのクラスはobjectのサブクラスである
print(isinstance(language2, object))
==> True
print(isinstance(animal1, object))
==> True
関連情報:type関数の使用方法
関連情報:isinstance関数の使用方法
初期化メソッド(コンストラクタ)・インスタンス変数の定義
# 初期化メソッド(コンストラクタ)、名前は __init__ で固定
class Person:
def __init__(self, number, name):
# インスタンス変数の定義
self.number = number
self.name = name
person1 = Person(1, 'Zhang')
print(vars(person1))
==> {'number': 1, 'name': 'Zhang'}
# インスタンス変数へのアクセス
print(person1.number)
==> 1
print(person1.name)
==> Zhang
# 初期化の際に引数を設定していないのでエラー
person2 = Person()
==> TypeError: __init__() missing 2 required positional arguments: 'number' and 'name'
# 初期化メソッドの引数にデフォルトの値を指定することも可能
class Animal:
def __init__(self, name='python', age=0):
self.name = name
self.age = age
# 引数を与えてインスタンス化
animal1 = Animal('snake', 100)
print(vars(animal1))
==> {'name': 'snake', 'age': 100}
# デフォルト値が設定してあるので引数なしでもインスタンス化できる
animal2 = Animal()
print(vars(animal2))
==> {'name': 'python', 'age': 0}
class Student:
# nameのみ必須、numberは任意
def __init__(self, name, number=0):
self.name = name
self.number = number
# 引数が足りないのでエラー
student1 = Student()
==> TypeError: __init__() missing 1 required positional argument: 'name'
# 必須の引数のみの設定
student2 = Student('Noah')
print(student2.name, student2.number)
==> Noah 0
# すべての引数の設定
student3 = Student('Olivia', 123)
print(student3.name, student3.number)
==> Olivia 123
クラス変数・メソッドの定義
class Person:
# クラス変数の定義
type = 'humanity'
# 初期化メソッド
def __init__(self, name):
# インスタンス変数の定義
self.name = name
# メソッド定義(インスタンスメソッド)
def introduce(self):
print(f"I'm {self.name}!")
# クラス変数へのアクセス
print(Person.type)
==> humanity
# インスタンスオブジェクトからもクラス変数へアクセスできる
person1 = Person('Zheng')
print(person1.type)
==> humanity
person1.introduce()
==> I'm Zheng!
class PublicSchool:
managed_by = 'government'
def __init__(self, code, name):
self.code = code
self.name = name
# インスタンスメソッド
def show_instance_properties(self):
print(f'code: {self.code}, name: {self.name}')
# クラスメソッド
@classmethod
def show_manager(cls):
print(f'managed_by: {cls.managed_by}')
# staticメソッド
@staticmethod
def introduce():
print(f"This is a public school's static method.")
# staticメソッドの呼び出し
PublicSchool.introduce()
==> This is a public school's static method.
# クラスメソッドの呼び出し
PublicSchool.show_manager()
==> managed_by: government
# インスタンスメソッドの呼び出し(インスタンス化してないのでエラー)
PublicSchool.show_instance_properties()
==> TypeError: show_instance_properties() missing 1 required positional argument: 'self'
# インスタンスオブジェクトからもクラス・staticメソッドは呼び出し可能
p_school1 = PublicSchool('S_A', 'Umami School')
p_school1.introduce()
==> This is a public school's static method.
p_school1.show_manager()
==> managed_by: government
p_school1.show_instance_properties()
==> code: S_A, name: Umami School
クラスの継承
# 基底クラス(base class、スーパークラス)
class Language:
def __init__(self, name):
self.name = name
def show_name(self):
print(f'name: {self.name}')
# 派生クラス(derived class、サブクラス)
class NaturalLanguage(Language):
pass
# NaturalLanguageクラスをインスタンス化
n_language1 = NaturalLanguage('English')
# 型はNaturalLanguage
# print(type(n_language1))
==> <class '{環境により異なる}.NaturalLanguage'>
# isinstanceは継承関係も考慮するため第2引数が基底クラスでも真となる
print(isinstance(n_language1, NaturalLanguage))
==> True
print(isinstance(n_language1, Language))
==> True
# 基底クラスのインスタンス変数にアクセス可能
print(n_language1.name)
==> English
# 基底クラスのインスタンスメソッドにアクセス可能
n_language1.show_name()
==> name: English
# 基底クラス
class Person:
def __init__(self, identifier, name):
self.identifier = identifier
self.name = name
def show_attributes(self):
print(f'identifier: {self.identifier}, name: {self.name}')
def introduction(self):
print(f"I'm {self.name}.")
# 派生クラス
class Student(Person):
# 初期化メソッド(コンストラクタ)のオーバーライド
def __init__(self, identifier, name, class_number):
# 基底クラス(スーパークラス)の初期化メソッドの呼び出し
super().__init__(identifier, name)
self.class_number = class_number
# インスタンスメソッドのオーバーライド
def show_attributes(self):
print(f'identifier: {self.identifier}, name: {self.name}, class_number: {self.class_number}')
# インスタンスメソッドのオーバーライド
def introduction(self):
# 基底クラス(スーパークラス)のメソッド呼び出し
super().introduction()
print(f'Class number is {self.class_number}.')
person1 = Person(1, 'Athena')
student1 = Student(2, 'Nike', 3)
# オーバーライドしたメソッドは挙動が異なる
person1.show_attributes()
==> identifier: 1, name: Athena
student1.show_attributes()
==> identifier: 2, name: Nike, class_number: 3
person1.introduction()
==> I'm Athena.
student1.introduction()
==> I'm Nike.
==> Class number is 3.
解説
クラスの定義・インスタンス化
Pythonのクラスは以下の記述方法で定義することができます。
# クラス定義
class クラス名:
{変数やメソッドなどの属性}
クラスはオブジェクトの型であり、
クラス定義ブロック内には変数やメソッド(関数)を定義することができます。
これらはクラスの属性
(attributes)と呼ばれます。
実際にクラスを元にしたオブジェクトを使用するためには該当クラスのインスタンス
を生成する必要があり、
その処理をインスタンス化
(原文:instantiation)と表現します。
クラスをインスタンス化するには関数やメソッドの呼び出し方と同様に、
クラス名の後ろに()
(丸括弧)をつけます。
# クラス定義
class Student:
pass
# インスタンス化
student1 = Student()
# Studentクラスのインスタンスであるかの確認
print(isinstance(student1, Student))
==> True
# strクラスのインスタンスではない
print(isinstance(student1, str))
==> False
初期化メソッド(コンストラクタ)・インスタンス変数の定義
独自クラスをインスタンス化する際、インスタンスに対して特有の変数の設定などを行いたい場合があります。
その場合はクラスに__init__メソッド(初期化メソッド)を実装してください。
__init__はPythonでは
特殊なメソッド名
であり、引数を設定することでインスタンス化の際に値を取得することができます。
第1引数にはself
という引数名で対象のインスタンス自体をとります。
(selfという名付けは慣習であり、別名でも良いですが推奨されません。)
self以外に指定した引数はインスタンス化の際に()
内で与えた引数の順で__init__メソッドに渡されます。
これらの値は__init__メソッド内でself.変数名 = 変数名
の形式でインスタンス内の変数に代入されることが多く、
このようなインスタンスに固有の変数をインスタンス変数
(instance variable)と呼びます。
注意点として、__init__メソッドにself以外の引数を定義した際には、インスタンス化時に同数の引数を与えないとエラーになることが挙げられます。
__init__メソッドの引数にデフォルト値を設定している場合はその限りではありませんが、インスタンス化時の挙動は
通常の関数・メソッドの呼び出し
に類似していることに気をつけてください。
class Language:
def __init__(self, id_number, name):
# インスタンス変数の定義
self.id_number = id_number
self.name = name
# 引数が足りないのでエラー
language1 = Language()
==> TypeError: __init__() missing 2 required positional arguments: 'id_number' and 'name'
language2 = Language(100, 'Python')
print(vars(language2))
==> {'id_number': 100, 'name': 'Python'}
# インスタンス変数へのアクセス
print(language2.id_number)
==> 100
print(language2.name)
==> Python
# 初期化メソッドの引数にデフォルトの値を指定
class Country:
def __init__(self, name='somewhere', code=None):
self.name = name
self.code = code
# デフォルト値が設定してあるので引数なしでもインスタンス化できる
country1 = Country()
print(vars(country1))
==> {'name': 'somewhere', 'code': None}
print(country1.name)
==> somewhere
print(country1.code)
==> None
# 引数ありのインスタンス化
country2 = Country('Japan', 392)
print(country2.name)
==> Japan
print(country2.code)
==> 392
クラス変数・メソッドの定義
クラスの代表的な属性として、インスタンス変数以外にも以下のものが挙げられます。
クラス変数(class variables)
クラス変数はインスタンス単位に異なるような値ではなく、そのクラスから生成されたオブジェクト全体で不変な値を設定することが推奨されます。
インスタンス変数と異なり、クラス名.クラス変数
の形式でインスタンス化せず呼び出すことができます。
クラスメソッド
クラスメソッドは定義する際に@classmethod
デコレータを使用します。
暗黙的に第1引数に呼び出したクラスオブジェクト(cls)をとり、その属性値にアクセスすることができます。
また、後述するインスタンスメソッドと異なり、クラス名.クラスメソッド
の形式でインスタンス化せず呼び出すことができます。
staticメソッド(静的メソッド)
staticメソッドは定義する際に@staticmethod
デコレータを使用します。
クラスメソッドと同様に、クラス名.staticメソッド
の形式でインスタンス化せず呼び出すことができます。
クラスメソッドと異なり暗黙の引数を取らないことに注意し、2つのメソッドを使い分けてください。
インスタンスメソッド
インスタンスメソッドはインスタンス化したオブジェクトから呼び出すことができます。
暗黙的に第1引数に呼び出したインスタンス自体(self)をとり、インスタンスの属性値にアクセスすることができます。
関連1次情報:デコレータ (decorator) - Pythonドキュメント
class Cat:
kind = 'felidae'
# 初期化メソッド
def __init__(self, name):
self.name = name
# インスタンスメソッド
def show_name(self):
print(f'name: {self.name}')
# クラスメソッド
@classmethod
def show_kind(cls):
print(f'kind: {cls.kind}')
# staticメソッド
@staticmethod
def meow(times=1):
print('meow~' * times)
# クラス変数へのアクセス
print(Cat.kind)
==> felidae
# クラスメソッドの呼び出し
Cat.show_kind()
==> kind: felidae
# staticメソッドの呼び出し
Cat.meow()
==> meow~
# インスタンスメソッドの呼び出し(インスタンス化してないのでエラー)
Cat.show_name()
==> TypeError: TypeError: show_name() missing 1 required positional argument: 'self'
# インスタンスオブジェクトからもクラス変数、クラス・staticメソッドは呼び出し可能
cat1 = Cat('Tama')
print(cat1.kind)
==> felidae
cat1.show_name()
==> name: Tama
cat1.show_kind()
==> kind: felidae
cat1.meow(3)
==> meow~meow~meow~
クラスの継承
他のプログラミング言語と同様にPythonもクラスの継承をサポートしています。
(Pythonは多重継承も実現可能ですがこのページでは解説しません。)
クラスを継承することで、継承されるクラスの属性(変数やメソッド)を継承したクラスで使用することができます。
属性値は継承したクラスでオーバーライド(上書き)することも可能で、継承したクラスで異なる振る舞いを実現することもできます。
それぞれの関係性は以下のように呼称されます。
継承されるクラス:基底クラス
(base class、スーパークラス)
継承したクラス :派生クラス
(derived class、サブクラス)
# PythonSchoolクラスの基底クラス
class School:
def __init__(self, name):
self.name = name
def show_attributes(self):
print(f'name: {self.name}')
def show_name(self):
print(f'This school name is {self.name}.')
# Schoolクラスの派生クラス
class PythonSchool(School):
# 初期化メソッド(コンストラクタ)のオーバーライド
def __init__(self, name, address):
super().__init__(name)
self.address = address
# インスタンスメソッドのオーバーライド
def show_attributes(self):
print(f'name: {self.name}, address: {self.address}')
# 新しいインスタンスメソッドの定義
def show_address(self):
print(f"{self.name}'s is {self.address}")
school1 = School('Normal School')
school1.show_attributes()
==> name: Normal School
# 派生クラスの属性(変数やメソッド)にはアクセスできない
print(school1.address)
==> AttributeError: 'School' object has no attribute 'address'
school1.show_address()
==> AttributeError: 'School' object has no attribute 'show_address'
p_school1 = PythonSchool('Python School', 'FooBar Street')
print(type(p_school1))
==> <class '{実行環境により異なる文字列}.PythonSchool'>
# isinstanceは継承関係も考慮され判定される
print(isinstance(p_school1, PythonSchool))
==> True
print(isinstance(p_school1, School))
==> True
# 基底クラスで定義した属性にもアクセスできる
print(p_school1.name)
==> Python School
p_school1.show_name()
==> This school name is Python School.
# 派生クラス(PythonSchool)でオーバーライドしたメソッドの挙動チェック
school1.show_attributes() # 基底クラスのオブジェクト
==> name: Normal School
p_school1.show_attributes() # 派生クラスのオブジェクト
==> name: Python School, address: FooBar Street
# 派生クラス(PythonSchool)で新定義したメソッド
p_school1.show_address()
==> Python School's is FooBar Street