クラスとは#
教科書 p.212(Lesson 8)プログラムが複雑になってくると、関数とそれに関するデータをまとめて扱いたくなります。 そのために、Python では クラス(Class) という概念が用意されています。 クラスは、関数とデータをまとめたもので、オブジェクト指向プログラミング(OOP; Object-Oriented Programming)の基本的な概念です。
なお、クラスは内部に関数や変数を含む大きな変数の定義に相当し、利用するには実体化(インスタンス化; instantiation)が必要です。 この作成された実体(インスタンス; instance)のことを オブジェクト(Object) と呼びます。
クラスを定義する#
クラスには、変数、関数を含められます。
クラスを定義するには、class キーワードを使います。
クラスの中身はインデントし、変数と関数を定義していきます。
クラスに含まれる関数は、最初の引数が self になっています。
self は、そのクラスのインスタンスを指します。
このような関数(クラスに含まれる関数のこと)を メソッド(Method) と呼びます。
また、クラスで定義される変数は、self.変数名 として利用できます。
このような変数のことを インスタンス変数(instance variable) と呼びます。
クラス内のメソッドとインスタンス変数は、クラスのインスタンス(オブジェクト)を通じてアクセスできます。 また、両者の名前の重複は許されず、あとから代入されたものが優先されます。
クラス利用の例#
class Person:
def get_name(self): # get_name は Person クラスのメソッド
return self.name # name は Person クラスのインスタンスに紐づいた変数
def get_age(self): # get_age は Person クラスのメソッド
return self.age # age も name と同じく、Person クラスのインスタンスに紐づいた変数
p = Person() # Person クラスをインスタンス化して(Personオブジェクトを作成して)
# p に Person クラスのインスタンス(Person オブジェクト)を代入する。
p.name = "John Doe" # Person オブジェクト p の変数 name に "John Doe" を代入する。
p.age = 30 # Person オブジェクト p の変数 age に 30 を代入する。
print(f"{p.get_name()} is {p.get_age()} years old.")実行結果#
$ python3 person.py
John Doe is 30 years old.- このプログラムでは、
Personクラスを定義し、get_nameメソッドとget_ageメソッドを定義しています。 - 続いて、
Personクラスをインスタンス化してpに Person クラスのインスタンス(Personオブジェクト)を代入します。 - そして、Personオブジェクトである
pの変数nameとageにそれぞれ"John Doe"と30を代入しています。 - 最後に、
Personクラスで定義されているget_nameメソッドとget_ageメソッドを呼び出して結果を出力しています。get_nameメソッド、get_ageそれぞれのメソッドの中でself.nameとself.ageとして、Personのインスタンス変数nameとageにアクセスしています。
ドット記法#
クラス利用の例でも見たように、インスタンス変数やメソッドにアクセスする際には、ドットを利用します。 このようなアクセス方法を ドット記法 と呼びます。
インスタンス名.インスタンス変数名
インスタンス名.メソッド名(引数リスト)複数のインスタンス(Multiple Instances)#
クラスを複数回インスタンス化することで、複数のオブジェクトを作成できます。 それぞれのオブジェクトは互いに影響せず、独立して動作します。
class Person:
def get_name(self):
return self.name
def get_age(self):
return self.age
def print(self): # 自分自身の情報を出力するメソッド(関数ではない)
print(f"{self.get_name()} is {self.get_age()} years old.")
def print_person(p): # Person を受け取り、その情報を出力する関数(メソッドではない)
print(f"{p.get_name()} is {p.get_age()} years old.")
p1 = Person() # 1つ目の Person オブジェクトを作成する。
p1.name = "John Doe" # p1 の name に "John Doe" を代入する。
p1.age = 30
p2 = Person() # 2つ目の Person オブジェクトを作成する。
p2.name = "Jane Doe" # p2 の name に "Jane Doe" を代入する。
p2.age = 35
# p1 の print メソッドを用いて、p1 の情報を出力する。
p1.print() # => John Doe is 30 years old.
# p2 の print メソッドを用いて、p2 の情報を出力する。
p2.print() # => Jane Doe is 35 years old.
# print_person 関数を呼び出し、p1 の情報を出力する。
print_person(p1) # => John Doe is 30 years old.
# print_person 関数を呼び出し、p2 の情報を出力する。
print_person(p2) # => Jane Doe is 35 years old.p1、p2はともに Person オブジェクトですが、それぞれ別の name、age という変数を持っています。
同様に、get_name、get_age、print メソッドもそれぞれのオブジェクトに紐づいています。
そのため、どのオブジェクトに対して、メソッドを呼び出したかによって、結果が異なります。
やってみよう: メソッドを追加する#
person2.py を person4.py という名前でコピーし、Person クラスに次の 2 つのメソッドを自分で追加してください。
is_adult: 年齢が 18 歳以上ならTrue、そうでなければFalseを返す。greet:"Hello, I am John Doe."のような挨拶の文字列を返す(表示するのではなく、返す)。
追加できたら、3 つ目のオブジェクト p3(名前 "Taro Yamada"、年齢 15)を作り、p1、p2、p3 のそれぞれについて greet の返り値と is_adult の結果を表示してください。
実行結果は次のようになります。
Hello, I am John Doe. True
Hello, I am Jane Doe. True
Hello, I am Taro Yamada. Falsep1.greet() と p3.greet() は同じメソッドを呼び出しているのに結果が違います。
self がそれぞれ別のオブジェクトを指しているからです。
🏁 解答例
class Person:
def get_name(self):
return self.name
def get_age(self):
return self.age
def print(self):
print(f"{self.get_name()} is {self.get_age()} years old.")
def is_adult(self): # 追加: 18 歳以上なら True。
return self.age >= 18
def greet(self): # 追加: 挨拶の文字列を返す(表示はしない)。
return f"Hello, I am {self.name}."
p1 = Person()
p1.name = "John Doe"
p1.age = 30
p2 = Person()
p2.name = "Jane Doe"
p2.age = 35
p3 = Person()
p3.name = "Taro Yamada"
p3.age = 15
print(p1.greet(), p1.is_adult())
print(p2.greet(), p2.is_adult())
print(p3.greet(), p3.is_adult())self#
selfは習慣的に、そのクラスのインスタンスを指す変数の名前として使われます。
習慣的に、ですので、別の名前でも構いません。
ただし、self 以外の名前を使うと、他のプログラマが混乱する可能性があるため、self を使うことが推奨されます。
class Person:
def get_name(s): # self という名前でなくても良い。
return s.name # この場合、s という名前でインスタンス変数を利用する。
# return name # s という名前を省略すると、単なるローカル変数として扱われる。
# # そのような変数はないので、エラーになる。
def get_age(self):
return self.age
p = Person()
p.name = "John Doe"
p.age = 30
print(f"{p.get_name()} is {p.get_age()} years old.")