オブジェクト、クラスの基本
記事の内容
この記事では、オブジェクトとは何か、について基本的なことを説明します。Pythonに限らず、多くのプログラミング言語でオブジェクトの概念が取り入れられています。オブジェクトの概念が取り入れられたプログラミング言語のことを「オブジェクト指向」のプログラミング言語といいます。
プログラミング初心者にとってオブジェクトの概念は難しく感じるかもしれません。しかし、オブジェクトの概念を取り入れることにより、プログラムの再利用やデータの取り扱いが飛躍的に簡単になります。やりたいことさえ明確であればプロでなくても実用性の高いプログラムを作ることができるようになるのです。
***わからない用語があるときは索引ページへ***
1.オブジェクトとは
まずはPythonプログラミングの観点でオブジェクトとは何かについて説明します。
Pythonのすべてのオブジェクトは、代入演算子"="を使って変数に代入できます。したがって、Pythonのオブジェクトとは「変数に代入できるものの総称」であると考えるとイメージがわきやすいかもしれません。これは他のプログラミング言語でも概ね同じなのですが、言語によってはオブジェクトの型(種類)によって宣言の仕方が違ったりするのであえて「Pythonの」と書きました。
具体的には以下のようなものがオブジェクトとして扱われます。わからないものが含まれていても今は気にしなくて良いです。
・データ(数値型、文字列型、ありとあらゆる型のデータ)
・データ構造(listや辞書、タプルなど)
・変数、定数、式
・関数
・クラス、インスタンス
・モジュール、パッケージ
・アプリケーション(Excel、メールソフト、Webサーバ、etc)
他、多種多様
アプリケーションのExcelというのは厳密にいうとExcelそのものではなく、Excelを操作するオブジェクト。このように、アプリケーションやファイルを操作するオブジェクトを「ハンドラー」といいます。
2.オブジェクトの基本
2.1.すべてのオブジェクトは型をもつ
すべてのオブジェクトは型をもっています。
文字列型のデータ(オブジェクト)で使えるメソッドは、数値型のデータでは使えません。また、文字列型のデータと数値型のデータを足し算することもできません。
このように、オブジェクトの型によって、できることが異なります
オブジェクトの型は"type()"関数を使って、
type(<オブジェクト>)
の形式で確認することができます。ためしにいくつかのデータを使ってそれぞれのオブジェクトの型をみてみましょう。
str1 = "文字列"
print("文字列のオブジェクトタイプ:", type(str1))
print("\n")
num1 = 3
print("整数型のオブジェクトタイプ:", type(num1))
print("\n")
num2 = 1.1
print("浮動小数型のオブジェクトタイプ:", type(num2))
実行結果は以下のように出力されます。
文字列のオブジェクトタイプ: <class 'str'>
整数型のオブジェクトタイプ: <class 'int'>
浮動小数型のオブジェクトタイプ: <class 'float'>
classの後ろの'(シングルクォーテーション)で囲まれた部分がオブジェクトの型を表しています。
2.2.クラス(class):オブジェクトの作成(定義)
クラス"class"とは、オブジェクトを定義した(Pythonの)プログラムのことです。オブジェクトには「型」があると説明しましたが、オブジェクトの型は全て、Pythonプログラムのクラス"class"で作成(定義)されています。つまり、オブジェクトの型とは、そのオブジェクトを定義しているクラス名のことです。
Pythonでは、class宣言を使ってオブジェクトを作成します。class宣言をすると、def宣言で関数を作るときと同じような感じで、オブジェクトを自作できます。class宣言によるオブジェクトの作成方法については、別の記事で紹介します。
2.3.メソッド
メソッドとは、クラスで定義されたクラス専用の関数のことです。メソッドの主な役割は、そのクラスのオブジェクトを操作することです。
メソッドは、
<オブジェクト>.<メソッド名>(引数1, 引数2, ・・・)
の形式で呼び出して、関数と同じように利用することができます。
イメージがつかみにくいときは、こちらの記事で文字列型データのメソッドの使い方を説明していますので、合わせて読んでみてください。
利用できるメソッドの種類は、オブジェクトの型、すなわちどのクラスのオブジェクトかによって決まります。中にはメソッドをもたないオブジェクトもあります。
2.4.オブジェクトの便利さを体感してみる
ここでは、"MailClient"という名前で定義された架空のクラスを使って、少しだけオブジェクトプログラミングの便利さを体感してみましょう。(下記のサンプルプログラムobj_ex1.pyは架空のクラスを使っており、コピペしても動きませんのでご注意ください)。
"MailClient"クラスの中身がどうなっているかわからなくても、プログラムを読めば何をしているかだいたいおわかりいただけると思います。また、部品としてプログラムに取り込み、簡単に再利用できるイメージも持てるのではないでしょうか。
##obj_ex1.py
##メールクライアントのオブジェクト利用例
##このプログラムは架空のクラスを使っているのでコピペしても動きません
##MailClientクラスが記述されたmcモジュールを読み込む
import mc
##MailClientクラスのインスタンスを生成する
mail_server = "smtp.example.com"
login_id = "suzuki_taro"
password = "xxxxx"
instance1 = mc.MailClient(mail_server, login_id, password)
##メール送信に必要なインスタンス変数をセット
instance1.to = "yamada_hanako@example.jp"
instance1.from = "suzuki_taro@example.jp"
instance1.subject = "〇×の件について"
instance1.attache = r"c:\path\to\file.txt"
instance1.body = \
'''
山田さん
鈴木です。
〇×の件についてよろしくお願いします。
詳細は添付ファイルを見てください。
'''
##send()メソッドでメールを送信する
instance1.send()
obj_ex1.pyでは、suzuki_taroさんが、メールサーバsmtp.example.comを使って、yamada_hanakoさんに添付ファイル付きのメールを送信しています。
以降、obj_ex1.pyに沿って、インスタンスとは何か、インスタンス変数とは何か、について説明していきます。
多くのクラス(すべてのクラスではない)は、代入文でインスタンスを生成してから利用します。obj_ex1.pyのMailClientクラスも、最初に
instance1 = mc.MailClient(mail_server, login_id, password)
でinstance1というインスタンス名のインスタンスを生成してから動かしています。インスタンス生成の時に、メール送信サーバと、メール送信サーバの認証情報を引数として渡しています。
インスタンス生成の記述規則は、
<インスタンス名> = <クラス名>(引数1, 引数2, ・・・)
となります。引数をもたないクラスのインスタンスを生成するときも、()をつけてインスタンスを生成します。
2.5.プロパティ、インスタンス変数、クラス変数、インスタンスメソッド、クラスメソッド
オブジェクトは、メソッドだけでなく、クラス専用の変数をもつことができます。この、クラス専用の変数は、プロパティ、またはクラス属性(class attribute/クラスアトリビュート)ともいいます。サンプルプログラムobj_ex1.pyの中の、to, from, subject, attach, bodyは、MailClientクラスのプロパティです。
##メール送信に必要なインスタンス変数をセット
instance1.to = "yamada_hanako@example.jp"
instance1.from = "suzuki_taro@example.jp"
instance1.subject = "〇×の件について"
instance1.attache = r"c:\path\to\file.txt"
instance1.body = \
'''
山田さん
鈴木です。
〇×の件についてよろしくお願いします。
詳細は添付ファイルを見てください。
'''
##send()メソッドでメールを送信する
instance1.send()
上記部分で生成したインスタンスのプロパティに送信メールの情報をセットし、最後にsend()メソッドでメールを送信しています。
ここで、obj_ex1.pyでは、
instance1 = mc.MailClient(mail_server, login_id, password)
の文でMailClientクラスのインスタンスinstance1を生成した後で、
<インスタンス名>.<インスタンス変数名>
の記述規則でインスタンスのプロパティにデータを代入しています。
インスタンスを生成した後で読み書きできるプロパティのことを、インスタンス変数と呼びます。
インスタンスと、インスタンス変数を混同しないようにしましょう。
インスタンス変数は、インスタンスごとに独立して扱われます。
次の例をみてみましょう。
##obj_ex2.py
##MailClientクラスが記述されたmcモジュールを読み込む
import mc
##MailClientクラスのインスタンスを生成する
mail_server = "smtp.example.com"
login_id = "suzuki_taro"
password = "xxxxx"
##MailClientクラスのインスタンスを2つ生成
a = mc.MailClient(mail_server, login_id, password)
b = mc.MailClient(mail_server, login_id, password)
##それぞれのインスタンスにインスタンス変数をセット
a.to = "xxx@xxx.com"
b.to = "yyy@yyy.com"
途中省略
##send()メソッドを使ってxxxさんとyyyさんに計2通メールを送信
a.send()
b.send()
aとbはどちらもMailClientクラスのインスタンスですが、それぞれ独立した別のインスタンスです。したがって、インスタンスaのインスタンス変数toとインスタンスbのインスタンス変数to(a.toとb.to)も互いに独立しています。
つまり、obj_ex2.pyでは、MailClientクラスのインスタンスを2つ生成し、それぞれのインスタンスで別々の人に1通ずつメールを送信しています。
上記のように、インスタンス変数は、インスタンスごとに独立した別の変数として扱われます。
プロパティには、インスタンスを生成して初めて読み書きできるインスタンス変数と、
<クラス名>.<クラス変数名>
の形式で、インスタンスを生成することなく、クラスから直接読み書きできるクラス変数があります。
また、メソッドも、インスタンスを生成して初めて呼び出すことのできるインスタンスメソッドと、
<クラス名>.<メソッド名>()
の形式で、インスタンスを生成することなく、クラスから直接呼び出すことができるクラスメソッドがあります。
クラス変数とクラスメソッドの詳細については、クラスの作成の記事で説明します。
2.6.定数や演算式はインスタンス?クラス?
定数、演算式は変数に代入することができます。ということは定数や演算式も、オブジェクトです。
となると、定数や関数、式はインスタンス?クラス?どちらでしょう。
答えは「特別なインスタンス」です。定数、演算式は、Pythonのインタープリターで定義されたフォーマットの書式を使い、代入文を使うことなく直接生成された特別なインスタンスです。
定数、式はインスタンスなので、プログラムの中でインスタンスとして扱うことができます。
サンプルプログラムをみてみましょう。
##文字列定数で文字列クラスのインスタンスメソッドを使う
str1 = "2020-6-05".replace("6", "06")
print(str1)
##listの連結式をインスタンスと同じように記述してみる
list1 = [1, 2]
list2 = [3, 4]
n = (list1 + list2)[3]
print(n)
実行結果
2020-06-05
3
文字列型の定数"2020-06-05"や、式"(list1 + list2)"がプログラムの中でインスタンスとまったく同じように扱えることがわかると思います。
文字列型データ、数値型データ、ブール型データ(True,False)のように、直接定数が記述できるデータ型の定数を総称して、リテラルと呼びます。リテラルは変数名をもたないインスタンスと考えると良いでしょう。
次の記事では、標準ライブラリで提供されているクラスを使って、外部クラスオブジェクトの利用例について説明します。
この記事が気に入ったらサポートをしてみませんか?