Pythonはオブジェクト指向言語の一つです。オブジェクトというのは部品のようなもので、既存の部品を組み合わせてプログラムを作っていくのがオブジェクト指向のプログラミングです。オブジェクトにはデータと命令(コード)が収められており、データに対して様々な処理を実行する働きを持ちます。
オブジェクトの設計図に当たるものがクラスです。各オブジェクトはデータとしてどんな値をとれるか、どんな処理ができるか、が定められています。クラスはこれらを定めた設計図であり、オブジェクトの構造を決めるひな形としての役割があります。クラスには変数と関数が含まれていて、クラスの中でそれぞれ定義されます。変数はデータの属性を定め、関数はそのデータに対する処理を定めます。
クラスから作ったオブジェクトがインスタンスです。この「作る」というのを「実体化」とか「具象化」とか表現します。クラスにはデータと命令(コード)が含まれていることを述べました。これらを使うためにインスタンスを生成する必要があるのです。
クラスとインスタンス、オブジェクトの関係は車の例で説明されることがよくあります。例えば、Civicという名前の車があったとします。この「Civicの設計図」がクラス、この「設計図を基に作られたCivic」がインスタンス、Civicという枠組みに当たる「自動車」がオブジェクトです。
インスタンスはクラスという設計図(概念)を実体化したものです。だいたいにおいてオブジェクトはクラスから生成されますから、オブジェクト≒インスタンスとなります。そのため、実際には両者を使い分けないことも多いようです。
Pythonに標準で備えられたクラスとして、10進数浮動小数点を扱うためのDecimalがあります。組み込みの浮動小数点型の数値は、演算のときに誤差が生じることがあります。例えば、以下です。
In
x = 0.1 + 0.1 + 0.1
print(x)
y = x - 0.3
print(y)
Out
0.30000000000000004
5.551115123125783e-17
誤差自体は小さいのですが、プログラムを作るときに厄介な問題となります。普通に考えれば、x - 0.3はゼロになるはずですから、それを条件にした処理を作ってしまうことがあります。[ if (x - 0.3) == 0, do next :x-3 がゼロなら、次の処理を実行 ]みたいな。この場合、この処理は永遠に実行されないことになってしまいます。これは、Pythonが2進数をベースに演算を行っているためですが、普通の数値計算ならこの程度の誤差は問題にならないことが多いです。
この誤差を回避したい場合に、Decimalクラスを使います。以下では、パッケージdecimalからモジュールDecimalをインポートして、10進数の数値ををデータに持つオブジェクトを作ります。ここで、「from decimal import Decimal」はDecimalクラスを使う準備をしており、「num = Decimal()」はクラスDecimalのインスタンスを作っている、ということができます。
In
from decimal import Decimal
num = Decimal(20)
print(num)
Out
20
変数numに入っている数値を、Decimalクラスのインスタンスといいます(オブジェクトということもあります)。で、Decimalクラスのインスタンスは、プログラムの中で組み込み型の数値型変数と同じように利用できます。以下は、Decimalクラスのインスタンスを使った四則演算の例です。
In
print(num + 30)
Out
50
Decimal(x)の引数xに小数点以下の数値を渡すときは、クォーテーションあるいはダブルクォーテーションで囲って文字列にします。浮動作法数点型のまま引数に渡すと、誤差が出ます。
In
x = Decimal(1.30)
y = Decimal("1.30")
z = Decimal(1)
print(x)
print(y)
print(z)
Out
1.3000000000000000444089209850062616169452667236328125
1.30
1
Decimalクラスのインスタンスには、メソッドもあります。
In
d = Decimal(100)
print(d.sqrt())
print(d.is_finite())
print(d.log10())
Out
10
True
2
既存の関数だけではなく、自身が独自に作った関数を使いたいことがあります。このようなとき、クラスを作ります。クラスは、オブジェクトがデータとしてどんな値をとれるか、どんな処理ができるか、を定めるもの、設計図でした。このクラスの設計図を作ることを、クラスの定義といいます。
クラスの定義では、どのようなデータ(変数、属性)が保存されており、どのような命令(関数、メソッド)を持つかを定めます。クラスを定義するとき、メンバ(変数)、メソッド(関数)、コンストラクタ(関数)といった用語を使うことがあります。メンバはクラスが持つ値で、変数のことです(属性と呼ばれることもあります)。メソッドはクラスが行う処理で、関数のことです。コンストラクタは、クラスを作るときに最初に呼び出される関数です。
メンバ:変数、属性
メソッド:関数
コンストラクタ:クラス作成時に呼ばれる関数
で、クラスを定義するには、「class クラス名:」と記述します。その後に、クラスの内容を記述していきます。クラス名は、大文字で始まる英文字を割り当てておきます。関数を小文字で表すことが多いので、クラス名を大文字にしておけば、両者を区別しやすいです。
class MyClass: # クラスの定義
pass # 何の処理も行わない
クラスから作られたオブジェクトが、インスタンスでした。今定義したクラスを使って、インスタンスを作ります。インスタンスを作るには、クラスを関数のように呼び出せばよいです。変数c1に、クラスMyClassから作ったインスタンスを代入します。このクラスは何の処理も行いませんから、これを実行しても何も出力されません。
In
class MyClass:
pass
c1 = MyClass()
Out
変数は、代入を行うことで定義されます。インスタンスのメンバ(変数)も同じように、代入を行うことで定義されます。メンバに代入するには、インスタンス名に"."(ドット)をつけて、メンバ名(変数名)を書きます。つまり、インスタンスのメンバ(変数)に代入を行えば、そのメンバ(変数)が定義されるのです。
In
class MyClass:
pass
c1 = MyClass()
c1.value = 10 # 変数名valueに数値を代入
print(c1.value) # 変数valueの値を表示
Out
10
メンバ(変数)に代入を行わないと、そのメンバ(変数)は定義されていないことになります。未定義のものはエラーになります。
In
class MyClass:
pass
c1 = MyClass()
print(c1.value1)
Out
---------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-7-a043184adf1d> in <module>
4 c1 = MyClass()
5
----> 6 print(c1.value1)
AttributeError: 'MyClass' object has no attribute 'value1'