Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Pythonのクラスについて

【Python入門】クラスとは何か?初心者にわかりやすく解説

具体例を使ってPythonのクラスの基本についての入門解説

今回はPythonのクラスについて超初心者向けの解説です。

クラスという概念・仕組みはオブジェクト指向という考え方と相まってプログラミング初心者にとってわかりにくいものの1つですね。

クラスの解説はプログラミング言語の種類や読者層によって千差万別の解説が溢れていますが、今回はPythonのクラスについて初心者向けに具体なコード例を使った説明をします。

今回の解説内容

今回はPythonのクラスについて、「共通要素をまとめる」という機能の1つに焦点をあてながら、あくまでクラスの初歩的なイメージを持っていただくための記事で、クラスの書き方・使い方の文法それ自体については特別な解説はしません。

クラスとは何か?なぜ必要なのか?その2つの機能(観点)から考える

なぜクラスという仕組みがあるのか?

なぜクラスという仕組みが存在しているのかといえば、それは開発効率・合理性を上げるためです。

特に長いコードを書くときや、大規模な開発における効率をアップさせるための手段・道具です。

クラスとは何か?2つの機能(観点)

クラスとは、ものすごく大雑把にいって次の2つの機能を実現する仕組み・概念のことです。

機能1共通要素をまとめる
機能2使いまわししやすくする

そこでクラスとは何か?をものすごく乱暴に言ってしまうと、「共通要素をまとめた」もので、「使い回ししやすい」ように用意された仕組み・概念、ということになります。

クラスの定義については、本当はポリモーフィズム(多態性)がどうこうとか継承がどうこうとかも関係してくるのですが、今回はそのへんの面倒な考えは一切考慮していません。

以下、簡単な具体例のコードとともに見ていきましょう。

クラスの作り方と使い方の具体例

クラスの作り方と考え方

まずは機能1の共通要素をまとめるという機能を見ていきましょう。

みなさんは中学校の数学で習った因数分解を覚えているでしょうか。たとえば、

ab + ac = a(b + c) 

というやつですね。共通要素aでくくっているわけです。

クラスの機能1はまさにこれと同じです。いろいろなパーツに共通する要素をまとめて、前にくくりだしているだけです。

こういった因数分解の考え方は数学の世界だけの話じゃなくて、普通に現実の社会でも意識して使っていますよね。たとえばゴミを捨てるときには、たくさんあるゴミをいちいち1つずつゴミ捨て場に運んでいきませんよね。ダンボールなどにまとめてからゴミ置き場にもっていきますよね。

またコンビニなどのチェーン店は、各支店ごとに異なる独自の決済システム、発注システム、人事システムなどを各店舗ごとに作りませんよね。各店舗共通のシステムは本部が開発・提供します。

同じものはまとめる。それがクラスの機能の1つです。コンビニチェーンでいえば、各店舗に共通する根幹システムのイメージです。

実際に超単純なコード例を見てみましょう。たとえばあるブランドの営業所として支店1(東京)と支店2(大阪)があったとします。各店の名前と住所という変数、そして売上を計算する関数を次のように作ったとします。

#支店1について
store1_name = "新宿店"
store1_place = "東京"
 
def sum_store1_sales():
    売上を合計する処理


#支店2について
store2_name = "日本橋店"
store2_place = "大阪"
 
def sum_store2_sales():
    売上を合計する処理

もちろんこれはこれでわかりやすくて良いと思います。ですが、どちらの営業所も、

  • 店の名前という情報
  • 店の住所という情報
  • 売上を合計する関数

という3種類の情報が存在しているという点で共通しています。そこでそれら共通要素をくくりだして、クラスを作ってみたコードが次のものになります。

class Store:
    # 各店舗の名称と住所の情報を設定
    # 引数selfには、インタンス自身が入る
    def __init__(self, store_name, store_place):
        self.name = store_name
        self.place = store_place
    
    # 各店舗の売上合計を出す処理
    # 引数selfには、インタンス自身が入る
    def sum_sales(self):
        print("100万円です")

クラスの使い方とインスタンス

このようにクラスができたわけですが、これはあくまで本部が各店舗に共通するシステムを作っただけなので、クラスを作った時点では新宿店や大阪店という各店舗が実際に作られたわけではありません。「共通する要素をまとめたもの」と、「それを利用する存在」とは全く別の情報(データ)です。

そこで次に各店舗を実際に作る(建設して稼働させる)作業へ入ります。次のようにします。

store1 = Store("新宿店", "東京")
store2 = Store("日本橋店", "大阪")

store1とstore2がクラスのインスタンスオブジェクト(単にインスタントとも呼ぶ)となります。このようにクラスは、代入文を使ってインスタンスを作るという使い方をします。

このようにしてから、

store1.name

を実行すると、

'新宿店'

と表示されます。

また、

store2.place

とすると、

'大阪'

と表示されます。

同じように、新宿店の売上合計金額を出したいときは、

store1.sum_sales()

とすると、

100万円

となります。

このように、

インタンス名.属性
または
インタンス名.メソッド()

という単純な書き方で使うことができます。これが最初に述べたクラスの機能2「使い回ししやすい」という機能の現れ方の1つです。

クラスを使うメリットとは?

上のコード例ではあまりクラスを使うメリットは感じられないと思いますが、クラスのメリットの1つについて上と同じ具体例を使って説明したいと思います。

上のクラスを作る前のコードを再び見てみます。

#支店1について
store1_name = "新宿店"
store1_place = "東京"
 
def sum_store1_sales():
    売上を合計する処理


#支店2について
store2_name = "日本橋店"
store2_place = "大阪"
 
def sum_store2_sales():
    売上を合計する処理

この場合、支店が増えてstore3、store4ができた場合、

#支店Xについて
storeX_name = "XXXXX"
storeX_place = "XXX"
 
def sum_storeX_sales():
    売上を合計する処理

というコードをひたすら付け足していくことになります。同じこと何度も何度も書いていくだけです。それはさすがにバカバカしいですよね。無駄にコードが長くなるだけです。

しかも、売上合計を出すシステム(関数)を修正しようとすると、全部の店舗のdef sum_storeX_sales()の中身を書き換えるハメになります。とても非効率的です。

一方でクラス化しておくと、クラス内部のメソッドを修正すればいいだけです。とても楽ですね。

クラスの属性とメソッド、そしてクラスメンバーとは?

クラスの中の情報は、メソッドと属性(アトリビュート)という2種類に大別されます。そしてこの2つをあわせて、クラスのメンバーと呼びます。

メンバーであるメソッドと属性の意味について大雑把にまとめた次の表を見てください。

メンバー
メソッド属性/アトリビュート
オブジェクトの動作(ビヘイビア)を決める関数メソッド以外のもので、オブジェクトの状態を決めるデータ

ただこのような分類は一般論(?)のようなもので、Pythonではメソッドも含めて属性と言われたり、用語の使い方が曖昧だったりすることもあるので、ある程度柔軟に考えておく必要があります。Python公式ドキュメント内部でも使い分けがめちゃくちゃな気もします。

いちおうPython公式ドキュメントの用語集では、

ドット表記式によって名前で通常参照される値

と書かれています。属性とは「値」というわけですね。

上のコード例でいうと、

class Store:
    # 各店舗の名称と住所の情報を設定
    # 引数selfには、インタンス自身が入る(第1引数にする)
    def __init__(self, store_name, store_place):
        self.name = store_name
        self.place = store_place
    
    # 各店舗の売上合計を出す処理
    # 引数selfには、インタンス自身が入る(第1引数にする)
    def sum_sales(self):
        print("100万円です")

これの関数__init__と関数sum_salesがメソッドで、nameやplaceといった変数の値が属性です。実際に使うときは、

インスタンス.name  # 値が返る
インスタンス.place  # 値が返る

などとして使いますから。

クラスを使う目的を忘れないことが大切

さて、以上のように便利そうなクラスですが、結局のところクラスも開発の効率性・合理性を向上させるための手段・道具の1つにしかすぎません。

それゆえクラスを作ることが逆に開発効率を下げるならば使うべきではない、ということになります。なんでもかんでもクラスにすればいいわけではない、ということですね。

そうした意識は、疎結合とか関数型プログラミングといった考え方・開発方法と密接に関連します。

以上かなり大雑把で乱暴な解説でしたが、Pythonのクラスの基本的なイメージは掴んでもらえたでしょうか。世界最大の動画学習サイトUdemyにもPythonの人気講座がいろいろあり、短期間でPythonをマスターすることができます。

愛を分かち合いましょう