Pythonでclassをどう使う?技術顧問に聞いてみた!

18/10/21 14:41:48     19/04/27 19:29:57

Pythonのクラス

Pythonは完全にオブジェクト指向型のプログラミング言語で、プリミティブ型の記述方法を採用していません。オブジェクト指向学習の最初の言語としてJavaを採用するケースも多いですが、Javaはオブジェクト指向型の書き方もできれば、プリミティブ型の書き方もできます。

オブジェクト指向型とプリミティブ型の違いはメモリ領域の取り方です。オブジェクト指向型の書き方ではオブジェクトのためのメモリ領域を確保したら、オブジェクトを使用する度にメモリのそこの領域を読みに行きます。

一方で、プリミティブ型の記述ではオブジェクトのように複数の場所から何度も同じメモリ領域を読みに行くことがありません。オブジェクト指向はインスタンス生成等で便利な面もありますが、メモリの節約にもなるのです。

こういった違いがありますが、よくわからない場合はスルーしておいてください。とりあえずメモリの使い方が異なるということです。話をPythonに戻すと、Pythonはオブジェクト指向の書き方しかできないため、Javaなどよりもオブジェクト指向を学習するのにちょうど良い言語だという意見もあります。

実際、Javaではオブジェクト指向の書き方もプリミティブ型の書き方もできるため、どう違うのかよくわからないまま学習しているケースも多いかと思います。そこでこのページでは、Pythonを例に、オブジェクト指向プログラミングにおけるclassの役割、使い方について解説していきます。

プログラミング画面

Python関連記事

オブジェクト指向におけるclassとは?

オブジェクト指向プログラミングにおけるclassとは、オブジェクトを作るための設計図です。Pythonに限らずオブジェクト指向言語ではclassの宣言をベースにプログラミングを進めていきますが、classはすべてオブジェクト生成のための設計図になります。

Javaなどではメインclassのなかでプリミティブな書き方をするケースも多いためよくわからなくなるかもしれませんが、classは本来設計図なので、classからオブジェクトを作り出すことで処理を行います。

classからオブジェクトを作り出すことをインスタンス生成と言います。図にすると以下のようになります。

class→インスタンス生成→オブジェクト

classからオブジェクトを作り出す処理が、インスタンス生成と覚えておくとわかりやすく、混同せずに済むかと思います。ただし、ややこしいことにclassに関係する概念はあと何個か存在します。

それでは、classと関係するその他の概念についても解説していきます。

classに関係する概念

classに関係する概念について上で少し説明しましたが、網羅的に挙げると以下のような概念があります。

  • オブジェクト
  • インスタンス生成
  • カプセル化
  • 情報隠蔽
  • ポリモーフィズム
  • オーバーライド
  • 継承

以上のような概念がclassに関連します。

オブジェクトとインスタンス生成

まずオブジェクトとインスタンス生成は上で説明した通りです。classからインスタンス生成することでオブジェクトを作成し、そのオブジェクトが処理を行うということです。つまり、classがオブジェクトのための設計図になります。

カプセル化と情報隠蔽

次にカプセル化と情報隠蔽についてですが、この二つの概念はセットになります。まずカプセル化とは、一連の処理を一つのclassにひとまとめにすることを指します。そして、そのカプセル化したclassを外部からアクセスできないようにする概念が情報隠蔽になります。

カプセル化という言葉だけで情報隠蔽を含むと考えるケースもあれば、情報隠蔽した際のclassのことをカプセル化されたclassと言う場合もあり、正直なところ言葉の定義は曖昧です。

なので書籍やWebサイトによって解説はまちまちなのですが、とりあえずclassを外部から容易にアクセスできないようひとまとめにすることをカプセル化や情報隠蔽と呼ぶ、と覚えておくとわかりやすいでしょう。

ちなみにPythonでのカプセル化の方法は、変数やメソッドの前に「__」を付けることでカプセル化できます。そのまま書くとわかりにくいのですが、「_(半角アンダーバー)」を二つ付けています。

Javaなどではprivateと書きますが、Pythonではアンダーバー二つです。アンダーバーを二つ付けてカプセル化すると、外部から参照できなくなります。外部から参照するためにはゲッターとセッターというメソッドの概念があり、これを使用することでカプセル化されたclassにも外部からアクセスできるようになります。

Javaなどと同様にPythonでも文法に従ってget、setを記述すればアンダーバー二つでアクセスを制限しているclassのメソッドも使えるのですが、get、setの記述でカプセル化したclassにアクセスしていたら、カプセル化した意味がない、という意見もあります。

言うなれば、classに鍵を掛けたけれど、誰でも簡単に開けられるような状態です。さらにPythonではより簡単にカプセル化されたclassにアクセスできるプロパティが用意されており、以下のように対応しています。

  • getter→@property
  • setter→@属性名.setter
  • deleter→@属性名.deleter

要するに、Pythonではカプセル化したclassにアクセスするための鍵が複数用意されており、メソッドを簡単に使用できます。

プログラミングする人

ポリモーフィズム

次にポリモーフィズムについてですが、多相性と和訳されます。そして、オーバーライドと継承もポリモーフィズムとセットで出てくる概念になります。まず目的から理解するとわかりやすいですが、ポリモーフィズム、オーバーライド、継承は大枠では同じ目的に使われるもので、「classの拡張利用」が主な目的になります。

classからインスタンス生成でオブジェクトを作って処理を行うのがオブジェクト指向言語の主な仕様で、classが設計図になることは上で説明した通りです。そして、当然ながらなるべくならいろいろなオブジェクトに対応できるclassを定義した方が汎用性があります。

この考え方がポリモーフィズムで、多相性ということです。そのポリモーフィズムの考え方とセットになるのが継承とオーバーライドです。まず継承とは、別classの定義を引き継いで新たなclassを作る概念になります。

大元のclassをスーパークラス、継承によって作った新たなclassをサブクラスと呼びます。ただし、当然そのまますべて同じように継承したらまったく意味がありません。同じ内容のclassが複数できるだけです。

オーバーライド、継承

そこで登場する概念がオーバーライドです。継承によってスーパークラスを引き継いでサブクラスを作りますが、その継承してできたサブクラスの中身を書き換える概念がオーバーライドになります。

オーバーライドによって書き換えるのはメソッドで、サブクラスではスーパークラスから継承したメソッドと、オーバーライドによって書き換えたメソッドの両方が使えることになります。

classを使い回すための概念がポリモーフィズムで、ポリモーフィズムを実現するためにスーパークラスからサブクラスを作り出す概念が継承、その継承のなかでメソッドを書き換えるための概念がオーバーライドということです。

Pythonのclass機能が必要な場合・不要な場合

Python以外のオブジェクト指向言語も同じですが、classからインスタンス生成することで具体的なオブジェクトを実装していきます。つまり、classは設計図のようなものです。また自分でclassを作らずとも、classライブラリというものが存在し、それを利用してオブジェクトを作ることも可能です。

このようにclassはオブジェクトを生成するための設計図なのですが、そもそもオブジェクトを作らずにそのまま処理をべた書きすることもできます。ステップ数が多かったりclassをいろいろな形で使いまわす場合にはclassの概念が便利ですが、逆にステップ数が少ない、同じような処理を使いまわすわけではない、といった場合はclassを書くことでかえってソースコードが冗長になります。

イメージとしては、たとえば自分で簡単な昼食を作ろうと思った場合、いちいちレシピを箇条書きでまとめることはないかと思います。しかし、すごく良いレシピだから後日またアレンジを加えて使いたい、または他の人にも共有したい、といった場合箇条書き等でレシピを残すでしょう。

このレシピがclassのようなものです。一回簡単に調理するだけならレシピを書くのはむしろ手間で、使いまわしや共有を行うからこそレシピが役立ちます。世の中の多くのPythonシステムはclassが使われていますが、レジの演算、データの収集といった単純処理を繰り返すだけのシステムではべた書きで実装されていることも多いです。

Pythonのclass機能を学習する前に

プログラミング学習は実際に手を動かすことも重要ですが、それと並行して大枠からの理解に努めた方が良いでしょう。すべての概念をきっちり完璧に理解する必要はありませんが、大枠を捉えたうえで実際に手を動かした方が「自分が今何を書いているのか」「なぜこのようなロジックになるのか」といったことが理解しやすいです。

よくわからないまま書いても動くには動きますが、肝心なところで混乱して手が止まってしまったり、バグの発生につながります。class機能についても同様で、よくわからないままclass機能の学習や実装に入るのではなく、classの概念や周辺知識をある程度固めてから実際の書き方を見ていくと良いでしょう。

まずシステム全体においてclassは個々のインスタンスの設計図の役割を果たします。インスタンスとは、実際の処理を指します。具体的には出力や計算などの処理はインスタンスが実行されているイメージです。

インスタンスと混同されがちな概念がオブジェクトですが、オブジェクトはざっくりとした網羅的な概念です。メソッドや変数すべてひっくるめてオブジェクトなので、classから作られるのはオブジェクトなのかインスタンスなのか、といった観点で悩む必要はありません。

classからインスタンス、もしくはオブジェクトを生成する、と理解しておくと良いでしょう。まずはclass、インスタンス、オブジェクト、の関係をざっくり把握しておけば、class機能の学習に入って混乱することも少ないかと思います。

逆に言えば、特にclassとインスタンスの関係性がよくわからないままclass機能の学習に入ると混乱します。

Pythonのclassを書いてみよう

簡単なコードで、classの作成からインスタンス生成、実行までの流れを確認してみましょう。サンプルコードは以下です。

class sampleClass:
     def function(self):
          print('class作成、インスタンス生成が成功し、出力されました。')
c = sampleClass()
print(c.function())

上記のソースコードを実行すると、以下のようにプリント出力されます。

class作成、インスタンス生成が成功し、出力されました。

それぞれのコードで何をやっているかですが、内訳は以下のようになります。

class sampleClass:
1行目では、sampleClassというclassを作成しています。このclassを元にインスタンス生成し、実行します。

def function(self)
2行目ではメソッドを作成しています。このメソッドの中に処理を記述します。

print(‘class作成、インスタンス生成が成功し、出力されました。’)
3行目では処理を記述しています。この処理はメソッドの中にあり、インスタンス作成と言われることもあります。

c = sampleClass()
4行目ではclassを元にcというインスタンスを生成しています。オブジェクト作成と言われることもありますが、同じ意味なので混乱しないようにしましょう。

print(c.function())
最後の5行目では生成したインスタンスのメソッドを呼び出し、それを出力しています。

以上が、基本的なclass作成の流れになります。高度なシステムもベースは同じなので、特にclass、インスタンス、オブジェクト、メソッド、といった概念で混乱しないように今のうちに押さえておきましょう。

classでコンストラクタを使う

コンストラクタとはオブジェクト生成の際に実行するメソッドです。Python以外のJavaなどでも出てくる概念なので、もし知っている方はそれと同じものになります。

具体的なコンストラクタの書き方は以下のようになります。

def __init__( self, 引数2, 引数3, ... ) :

「__init__」はPythonにおけるコンストラクタの名前で、任意ではなくこの名前でなくてはなりません。コンストラクタは特殊メソッドなので、名前というよりは一種のメソッドと考えた方が良いかもしれません。

第一引数のselfでオブジェクトを呼び出し、第二引数以降はクラス内の初期化したいものを指定します。省略することも可能です。それではサンプルコードでコンストラクタの使い方を確認します。

class Animal:
    def __init__(self, name):
        self.name = name

    def say(self):
        print("ペットの名前は" + self.name + "です。")

dog = Animal("犬")
cat = Animal("猫")

dog.say()
cat.say()

これを実行すると、「ペットの名前は犬です。」「ペットの名前は猫です。」となります。犬っぽい名前と猫っぽい名前を考えても良かったのですが、サンプルコードなのでシンプルにそのままにしてみました。

classでデストラクタを使う

デストラクタはコンストラクタの逆で、インスタンス破棄の際に呼び出されるメソッドです。書き方もコンストラクタと似ていて、以下のようになります。

class Foo:
    def __del__(self):

コンストラクタで__init__だったのが、デストラクタでは__del__になりました。サンプルコードは以下です。

class Foo:
    def __del__(self):
        print('デストラクタの呼び出し')

f = Foo()
print('インスタンスが生成された')
del f
print('インスタンスが破棄された')

上記のコードを実行すると以下のように出力されます。

インスタンスが生成された
デストラクタの呼び出し
インスタンスが破棄された

まずFooクラスを定義し、デストラクタ __del__ を実装しました。次にFooクラスのインスタンスを作成しています。最後にインスタンスを破棄したので、デストラクタが呼び出されました。

Pythonのclassコーディングが楽になるツール

Pythonのclassコーディングを楽にするにはPyCharmがベストでしょう。またclassコーディングだけでなく、コーディング全般が楽になります。コーディングを楽にするためにはライブラリやフレームワークももちろん重要なのですが、それ以上に入力補完が重要と言っても過言ではありません。

Pythonの場合ライブラリやフレームワークの機能で実装を進めることも多いですが、入力補完については入力するたびに関係することです。生産性や開発ストレスに大いに関係してきます。

そして入力補完は基本的にエディタの仕事ですが、PythonにおいてはPyCharmが圧倒的に便利だということです。PyCharmはIDE(総合開発環境)ですが、PythonでIDEを選ぶならPyCharm一択と言えます。(AWS Cloudなどを使用する場合は別)

入力補完が充実したテキストエディタも多いですが、Pythonに関してはエディタとしてもPyCharm主体で開発を進めるのがおすすめです。たとえばPythonによく出てくる「引数self」を自動入力するなどの機能があります。他のIDEやテキストエディタだとこのような機能はないかと思います。

classコーディングでは入力補完が便利ですが、classコーディングを広義に捉えて関連するコード全般に解釈を広げると、コード解析、型ヒント、データベース連携、といった機能も充実しています。

まとめ

それぞれの言葉の定義を明確に覚える必要はありませんが、classに関係する概念や、それぞれの使い方について説明してきました。Pythonは完全にオブジェクト指向型の言語なので、説明してきた概念に基づいてプログラミングを進めることになります。

個々の詳細な記述方法ももちろん重要なのですが、ざっくりとでも良いので概念は把握しておいてください。概念を把握しないまま個々の記述方法だけを追いかけても結局コピペによるつぎはぎになってしまうため、大枠を捉えていくことが重要です。

Python関連記事
1,【Pythonのフリーランス求人・案件情報】エンジニア開発単価は?未経験でもいける?
2,Pythonでできることとは?人工知能で強みを発揮!
3,Pythonのインストール方法をまとめてみた
4,Pythonプログラミングに便利なAnacondaとは?機能やPycharmとの違いを解説
5,PythonでAnacondaをインストールする方法から実際の使い方までを解説
6,Pythonの配列を徹底解説!宣言や追加・削除など
7,Pythonのif文の使い方を解説!演算子もおさらい
8,Pythonのfor文の使い方を配列で解説!breakやrangeの使い方もこれでOK
9,Pythonのlambda(ラムダ式)の使い方を徹底解説します
10,Pythonの高階関数map/filterの便利な使い方
11,Pythonでclassをどう使う?技術顧問に聞いてみた!(この記事)

人気記事

編集部おすすめ記事

この記事を読んだ人はこんな記事を読んでいます

案件探しやフリーランスになるための相談する