Pythonのクラスをわかりやすく解説!初心者でも挫折しないための入門ガイド

こんにちは。ゆうせいです。

プログラミングの学習、順調に進んでいますか?

「だんだん専門的なことが増えてきて、少し難しいな…」と感じている方もいるかもしれませんね。

特に、多くの初心者がつまずきやすいポイントの一つに「クラス」があります。

でも、安心してください!

クラスは一度理解してしまえば、あなたのプログラミングスキルを格段にレベルアップさせてくれる、とっても強力な武器になるんです。

今日は、新人エンジニアのあなたに向けて、Pythonの「クラス」という概念を、一緒に見ていきましょう。

「クラスって何?」「何が便利なの?」といった疑問に、一つひとつ丁寧に答えていきますよ。

クラスって、そもそも何?

早速ですが、あなたがたい焼き屋さんになったと想像してみてください。

たい焼きを作るとき、一つひとつ手で形を整えるのは大変ですよね?

普通は、「たい焼きの型」を使います。

この「たい焼きの型」、こそがクラスのイメージです。

クラスとは、簡単に言うと「オブジェクトの設計図」のことです。オブジェクトとは、プログラムの中で扱う「モノ」のことですね。

たい焼きの型があれば、あんこを変えたり、クリームを入れたりして、色々な種類のたい焼き(オブジェクト)を、同じ品質でたくさん作ることができますよね。

プログラミングにおけるクラスも、同じように、決まった構造を持つオブジェクトを効率的に作り出すための「設計図」や「型」の役割を果たすのです。

コードを分解して見てみよう!

では、具体的なコードを見ながら、クラスの仕組みを解き明かしていきましょう。

今回は、「購入した商品」を表す、次のようなシンプルなクラスを例にします。

class PurchasedItem:
    def __init__(self, item_name):
        self.item_name = item_name

    def get_item_name(self):
        return self.item_name


item = PurchasedItem('a cup of coffee')

item_name = item.get_item_name()

print('I bought', item_name, 'at a convenience store.')


一見すると複雑に見えるかもしれませんが、パーツごとに分解すれば、決して難しくはありません。

一緒にじっくり見ていきましょう!

1. 設計図を作る (クラスの定義)

class PurchasedItem:

最初のこの一行は、「これからPurchasedItemという名前のクラス(設計図)を作りますよ!」という宣言です。

classというキーワードの後に、あなたが好きなクラス名を続けます。今回は「購入した商品」なのでPurchasedItemと名付けられています。

ここが、まさしく「たい焼きの型」そのものを定義している部分にあたります。

2. オブジェクトが生まれた瞬間の処理 (__init__メソッド)

    def __init__(self, item_name):
        self.item_name = item_name

次に出てくるのが、__init__という、ちょっと変わった名前の関数ですね。

これは「メソッド」と呼ばれ、クラスの中で定義される関数のことです。

そして、この__init__メソッドは、「初期化メソッド」や「コンストラクタ」とも呼ばれる、とても特別なメソッドなんです。

何が特別かというと、このメソッドは、クラスから新しいオブジェクトが作られる(生まれる)瞬間に、自動的に一度だけ呼び出されるのです。

オブジェクトが作られたときに、最初にやっておきたい設定などを、この中に書いておきます。

たい焼きの例で言えば、「たい焼きが焼かれる(作られる)ときに、中に入れるあんこを決める」作業が、この__init__メソッドの役割です。

ここで、selfitem_nameという2つの「引数(ひきすう)」が出てきました。

  • self: これは、クラスから作られる「オブジェクト自身」を指す、お決まりの言葉です。たい焼きで言えば、「今まさに作られようとしている、このたい焼き」というイメージですね。メソッドを定義するときは、必ず最初にselfを書くルールになっています。
  • item_name: これは、オブジェクトを作るときに外から与える情報です。今回の場合、「購入した商品の名前」を外から受け取るために使います。たい焼きの「あんこの種類(あんこなのか、クリームなのか)」に相当しますね。

そして、self.item_name = item_nameという行。

これは、「外から受け取ったitem_name(例: 'a cup of coffee')を、このオブジェクトが持つitem_nameという変数に保存してください」という意味です。

self.変数名と書くことで、そのオブジェクト固有のデータを保存しておくことができます。これを「属性(アトリビュート)」と呼びます。

これで、「『a cup of coffee』という名前を持った、購入商品オブジェクト」が作られる準備が整いました。

3. オブジェクトができること (メソッドの定義)

    def get_item_name(self):
        return self.item_name

次もメソッドの定義ですね。get_item_nameという名前のメソッドです。

これは、このPurchasedItemオブジェクトができる「アクション(振る舞い)」を定義しています。

ここでもselfが登場しました。

このメソッドが呼び出されたときに、「どのオブジェクトの」名前を返せばいいのかをselfが教えてくれます。

return self.item_nameは、「このオブジェクトが持っているitem_name属性の値を返してください」という意味です。

たい焼きの例で言うなら、「このたい焼きの中身が何かを教えてくれる機能」のようなものです。

設計図から、本物のオブジェクトを作ってみよう!

さて、これまではクラスという「設計図」を定義してきただけでした。

ここからは、その設計図を使って、実際に「モノ(オブジェクト)」を作り出していきます。このプロセスを「インスタンス化」と呼びます。インスタンスとは、クラスから作られた実体のことです。

item = PurchasedItem('a cup of coffee')

この一行が、まさに「インスタンス化」を行っている部分です!

PurchasedItem('a cup of coffee')というコードで、PurchasedItemクラスの設計図を元に、新しいオブジェクトを1つ作成しています。

このとき、'a cup of coffee'という文字列が、先ほど説明した__init__メソッドのitem_name引数に渡されます。

そして、__init__メソッドが自動的に実行され、「item_nameが'a cup of coffee'である」という情報を持ったオブジェクトが生成されるわけです。

生成されたオブジェクトは、itemという変数に代入されます。

これで、itemという名前の、世界に一つだけの「購入商品オブジェクト」が誕生しました!

作ったオブジェクトを使ってみよう!

オブジェクトができたので、次は実際に使ってみましょう。

item_name = item.get_item_name()

このコードは、先ほど作成したitemオブジェクトに対して、「あなたが持っているget_item_nameメソッドを実行してください!」と命令しています。

オブジェクト.メソッド名()という形式で、そのオブジェクトが持つ機能を呼び出すことができるのです。

itemオブジェクトのget_item_nameメソッドは、self.item_nameを返すように作られていましたね。

itemオブジェクトのitem_nameは'a cup of coffee'なので、このメソッドは'a cup of coffee'という文字列を返します。

その結果が、item_nameという新しい変数に格納されます。

print('I bought', item_name, 'at a convenience store.')

最後の行では、取得したitem_name(つまり'a cup of coffee')を使って、文章をコンソールに出力しています。

結果として、画面には次のように表示されるはずです。

I bought a cup of coffee at a convenience store.

どうでしょうか?クラスの動きが少しイメージできましたか?

クラスを使うメリットとデメリット

ここで、なぜわざわざクラスなんてものを使うのか、そのメリットと、少し注意すべき点をまとめてみましょう。

解説
メリット
再利用性の向上一度クラスを作ってしまえば、同じ構造のオブジェクトを何個でも簡単に作れます。item2 = PurchasedItem('a piece of cake')のように、色々な商品オブジェクトを量産できますね。
整理整頓がしやすい商品の名前(データ)と、その名前を取得する処理(メソッド)が、PurchasedItemという一つのまとまりになっています。このように、関連するデータと処理をひとまとめにすることを「カプセル化」と呼び、コードがとても見やすく、管理しやすくなるのです。
保守性の向上もし将来、「商品の値段も管理したい」となった場合、PurchasedItemクラスに値段に関する属性とメソッドを追加するだけで済みます。関連するコードが一箇所に集まっているので、修正が楽になります。
デメリット
概念の難しさselfの考え方や、設計図と実体(オブジェクト)の関係など、最初のうちは少し抽象的で難しく感じるかもしれません。
コード量の増加ごく単純な処理の場合、クラスを使わずに書いた方が、コードの行数自体は短くなることもあります。

クラスは、特に中規模から大規模なプログラムを開発する際には、なくてはならない存在です。

初めは少し戸惑うかもしれませんが、この整理整頓の考え方に慣れると、コードを書くのがもっと楽しく、もっと効率的になりますよ!

はい、承知いたしました。「まとめと今後の学習指針」の前に、Javaとの比較に関するセクションを追加しますね。以下がその部分の文章です。


【番外編】Javaとの違いは?

新人研修などで、Javaを先に学んだという方もいるかもしれませんね。

「Pythonのクラスって、なんだかJavaと書き方が違うな?」と感じた方もいるのではないでしょうか。

その感覚、大正解です!

考え方の根っこは似ているのですが、PythonとJavaではクラスの書き方にいくつかの文化的な違いがあります。ここでは、特に重要な「フィールド(属性)の宣言」と「アクセス制御」について、少しだけ寄り道して見てみましょう。

フィールド(属性)の宣言方法

Javaでクラスを書くとき、まず最初にクラスがどんなデータ(フィールド)を持つのかを、メソッドの外で宣言するのが一般的です。

public class PurchasedItem {
    // 先にフィールドを宣言する
    private String itemName;

    // コンストラクタで初期化する
    public PurchasedItem(String itemName) {
        this.itemName = itemName;
    }
    // ...
}

これは、たい焼きの型の設計図に「この型には『あんこ』という項目があります」と、あらかじめ明記しておくようなイメージです。

一方で、今回学んだPythonのコードをもう一度見てみましょう。

class PurchasedItem:
    def __init__(self, item_name):
        # __init__の中で初めて属性を定義する
        self.item_name = item_name

Pythonでは、__init__メソッドの中で self.item_name = ... と書いた瞬間に、そのオブジェクトの属性が作られます。

Javaのように、あらかじめ属性を宣言しておく必要はありません。より柔軟で、動的な感じがしませんか?

「たい焼きを作るその瞬間に、『よし、こいつの中身はあんこだ!』と決めて、名札を付ける」ようなイメージに近いかもしれませんね。

アクセス制御 (public / private)

Javaには public や private といった「アクセス修飾子」があり、クラスの外部からフィールドやメソッドにアクセスできるか、厳密に制限することができます。

private を付けたフィールドは、そのクラスの中からしか触ることができません。これは、大事な部品をうっかり外から壊されないように、箱の中に厳重にしまっておくようなものです。

それに対して、Pythonには、実は private のような厳密なアクセス制限の仕組みがありません。

その代わり、「これはクラスの内部だけで使うつもりだよ」という開発者同士の合図として、変数名の前にアンダースコア _ を一つ付ける、という慣習があります。(例: self._item_name)

これは、「鍵のかかった箱」ではなく、「『関係者以外立ち入り禁止』の看板」のようなものです。ルールを知っていれば誰でも入ることはできてしまいますが、常識的に「あっ、これは触っちゃいけないんだな」と理解する、という文化なのです。

これらの違いを表にまとめてみましょう。

項目PythonJava
フィールド(属性)の宣言__init__メソッド内などで動的に定義する (self.name = ...)クラスの冒頭であらかじめ宣言する (private String name;)
アクセス制御アンダースコア _ を付けるなどの慣習で行う (紳士協定)public private などのキーワードで厳密に行う (強制的)
Getter/Setter必須ではない。直接アクセスすることも多い。privateフィールドとセットで用いるのが一般的。

このように、似ているようでいて、言語ごとの思想や文化が反映されているのは面白いですよね。

どちらが良いというわけではなく、それぞれの言語が持つ「らしさ」だと捉えてください。

さて、少し寄り道をしてしまいましたが、Pythonのクラスの解説に戻りましょう!

まとめと今後の学習指針

お疲れ様でした!今回はPythonの「クラス」について、基本的な概念と使い方を解説しました。

  • クラスは、オブジェクトを作るための「設計図」や「型」である。
  • __init__メソッドは、オブジェクトが作られるときに自動で呼ばれる初期化のための特別なメソッド。
  • selfは、作られたオブジェクト自身を指す。
  • クラスからオブジェクトを作ることを「インスタンス化」と呼ぶ。
  • オブジェクト.メソッド()で、そのオブジェクトの機能を使うことができる。

これらのポイントを、たい焼きの例えと共に思い出してみてください。

さて、クラスの第一歩は踏み出せました。でも、クラスの世界はもっと奥が深いんです!

もし、あなたが「もっとクラスを使いこなしたい!」と思ったら、次に何を学ぶべきか、指針を示しますね。

  1. 自分でクラスを作ってみよう!まずは、今日学んだことを真似して、自分で簡単なクラスを作ってみるのが一番です。例えば、Bookクラス(タイトルと著者を持つ)、Playerクラス(名前とHPを持つ)など、身の回りのものをクラスとして表現する練習をしてみましょう。
  2. 継承を学ぼう!クラスには「継承」という、さらに強力な機能があります。これは、既存のクラス(親クラス)の機能を引き継いで、新しいクラス(子クラス)を作る仕組みです。例えば、「動物」クラスを元に、「犬」クラスや「猫」クラスを作るといったことができます。コードの再利用性が飛躍的に高まりますよ。
  3. より多くの属性とメソッドを追加してみよう!今回の例は属性もメソッドも1つずつでしたが、実際の開発ではもっと多くの属性やメソッドを持つクラスを扱います。購入した商品の「値段」や「個数」といった属性を追加したり、「合計金額を計算する」メソッドを追加したりと、色々拡張してみてください。

クラスを制する者は、オブジェクト指向プログラミングを制します。

今日の学びをきっかけに、あなたのエンジニアとしての新たな扉が開くことを願っています。

頑張ってください!

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。