ここでは自分でクラスを定義する方法を説明します。
新規にクラスを定義するというのは、新しいオブジェクトの「型」を作ることと同意語です。クラス(型)を作り、そこから作られたインスタンスを作り利用します。インスタンスは、クラスで定義されているメソッド(処理)やインスタンス変数と呼ばれるインスタンス内に保持される値を持っています。
まずクラスの定義する方法を見てみます。
# File: helloclass.py
# クラス (class)
# https://docs.python.org/ja/3/tutorial/classes.html
#
class Hello:
myhello="Hello World"
def hello(self):
return self.myhello
def hello_jp(self):
localvar="こんにちは世界"
return localvar
def set_hello(self,message):
self.myhello=message
h=Hello() # インスタンスを生成
print(h.myhello) # myhello変数にアクセス
print(h.hello_jp()) # メソッドhello_jp()を呼び出し
h.set_hello('What\'s up') # 引数の与え方
print(h.hello()) # プリント
h.myhello="Aloha" # 直接myhello変数を書き換え
print(h.hello()) # 変化をチェック
h2=Hello() # 別のインスタンスh2を生成
print(h2.hello()) # インスタンスh2内の値をプリント
print(h.hello()) # インスタンスh内の値をプリント
Hello.myhello='コニャニャチワ' # クラス変数の値を変える
print(h2.hello()) # インスタンスh2内の値をプリント
print(h.hello()) # インスタンスh内の値をプリント
print(Hello.myhello) # クラス変数としての値をプリント
h3=Hello() # 別のインスタンスh3を生成
print(h3.hello()) # インスタンスh3内の値をプリント
del h # インスタンスの消去
del h2 # インスタンスの消去
del h3 # インスタンスの消去
class Hello:
クラス名Helloを宣言しています。
myhello="Hello World"
これはクラス変数と呼ばれるものです。クラスHelloでは1つの内部変数を持っています。この値はクラスそのものが保持しています。これをアクセスするには、このオブジェクトの持つオブジェクトなのでself.myhelloとします。selfは自分自身のオブジェクトを意味します。
クラスHelloはhello()、hello_jp()、set_hello()の3つのメソッドが定義されています。この時、最初の引数は自分自身のインスタンス(のオブジェクト)となります。
では、インスタンスを生成し、一通り試してみます。
h=Hello() # インスタンスを生成
print(h.myhello) # myhello変数にアクセス
print(h.hello_jp()) # メソッドhello_jp()を呼び出し
h.set_hello('What\'s up') # 引数の与え方
print(h.hello()) # プリント
h.myhello="Aloha" # 直接myhello変数を書き換え
print(h.hello()) # 変化をチェック
次に新しいインスタンスを生成し変数h2とします。次に変数hと変数h2の違いを観察してみます。
h2=Hello() # 別のインスタンスh2を生成
print(h2.hello()) # インスタンスh2内の値をプリント
print(h.hello()) # インスタンスh内の値をプリント
変数hの中のmyhelloの値は書き換わっているため、両者の出力は異なります。
Hello.myhello='コニャニャチワ' # クラス変数の値を変える
print(h2.hello()) # インスタンスh2内の値をプリント
print(h.hello()) # インスタンスh内の値をプリント
インスタンスではなくクラスのmyhelloの値を書き換えてみます。myhelloはクラス変数なので、h2.hello()の出力は変化します。一方で、h.hello()の出力は以前のままです。これはmyhelloを一度書き換えているので(myhelloに新しいオブジェクトをセットしているので)、既に異なっているためです。
クラス変数を書き換えると、クラス全体に変更が反映されるという説明を見かけますが、これは同じオブジェクトを共有していることを意味しているので、同じといういうだけで、既にオブジェクトを別のものにしている場合、当然ながら、そのオブジェクトのもつ値になります。形式的にはインスタンス変数と同じ考え方になります。id(Hello.myhello)、id(h.myhello)、id(h2.myhello)の値がどう変化していくかを観察するとよくわかると思います。
del h # インスタンスの消去
del h2 # インスタンスの消去
del h3 # インスタンスの消去
インスタンス(のオブジェクト)を消去するためにはdelを使います。
インスタンスを作る際に引数のかたちで初期化するための値を与える場合です。
# File: classdef.py
# クラス (class)
class NumberPool():
def __init__(self):
self.pool_of_numbers=[] # list型のインスタンス変数を作成
def add(self,number):
if (type(number) == int ): # 渡されたオブジェクトが整数ならば
self.pool_of_numbers.append(number)
return self.pool_of_numbers
else:
return None # 整数ではなかった
def get(self):
return self.pool_of_numbers # すべてを返す
def del_odd(self): # 奇数のみ消す
even=[]
for i in self.pool_of_numbers:
if (i % 2) == 0:
even.append(i)
self.pool_of_numbers=even
return self.pool_of_numbers
def join(self,pool_num): # poolを連結する
if (type(pool_num) == NumberPool):
self.pool_of_numbers += pool_num.get()
return self.pool_of_numbers
else:
return None
p0 = NumberPool()
p0.add(100)
p0.add(99)
print(p0.get())
print(p0.pool_of_numbers)
p1 = NumberPool()
p1.add(87)
p1.add(22)
print(p1.get())
print(p1.pool_of_numbers)
p0.del_odd()
print(p0.get())
p1.join(p0)
print(p1.get())
print(p0.get()) def __init__(self):
self.pool_of_numbers=[] # list型のインスタンス変数を作成
この__init__(self)はインスタンスが作られる時に必ず呼び出される名前が決められている特別なメソッドです。他の言語では「コンストラクタ」と呼ばれたりします。この中でインスタンス変数pool_of_numbersを中身が空のリストに設定しています。
他のオブジェクト指向言語の中にはプライベート(インスタンス)変数といって、外部からアクセスできない内部変数がありますが、Pythonにはありません。ただ書き方として foo (2つ連続したアンダーバーが前後につけられる)といった名前のインスタンス変数やメソッドはプライベートのつもり、という習慣(あるいはお約束ごと)があるようです。
def add(self,number):
if (type(number) == int ): # 渡されたオブジェクトが整数ならば
self.pool_of_numbers.append(number)
return self.pool_of_numbers
else:
return None # 整数ではなかった
これはクラスNuberPoolのメソッドaddを定義している部分です。最初はselfで、次が呼び出し時の引数です。引数として渡ってきたnumberが整数であればpool_of_numbersに蓄えられられます。もし整数でない場合、Noneを返します。