Pythonは物事を中心に捉えてコーディングしていくオブジェクト指向プログラミングが可能な言語です。その考え方の中でもclass(クラス)は根幹の概念であり、効率的にコードを書く上で重要な仕組みです。
クラスを活用すると、重複する内容を整理できたり、コードが読みやすくなったりするメリットがあるため、積極的に使用したい機能です。
ただし、プログラミング言語によってクラスを定義する方法が異なるため、Pythonを学ぶ上ではその記法を正しく理解しなければなりません。
この記事ではPythonのクラスの使用方法やメリットを解説していますので、これから学び始める方や洗練したコードを効率良く書きたい方はぜひ参考にしてみてください。
業務/Web系SEを経て、Web制作フリーランスとして独立。Webエンジニアとして研鑚を積みながら、ライターや講師業でアウトプットを行っています。
Pythonのclass(クラス)とは?

Pythonのclass(クラス)は、オブジェクト指向の考え方に沿ってアプリケーションの中で必要な物事を表現するための機能です。
アプリケーションの内容を人間が理解しやすいように物事を中心に捉えていき、物事の変化や振る舞いを表すためにクラスが使われます。現実世界のようにあたかも物事同士が連動しているかのように表現できるため、複雑なコードであっても直感的に理解しやすく置き換えることができます。
クラスで表現される物事はアプリケーションによって異なり、それはECサイトにおける販売商品であったり、タスク管理におけるタスクであったり目的によって様々です。それらの物事に関連する変数やメソッドなどの要素をクラスの中に集約することで、開発者にとって理解しやすいコードとなり、追加や修正が容易になるメリットをもたらします。
また、不用意なアクセスを禁止できる仕組みも備えており、意図しないアクセスによるバグの混入を防ぐ効果もあります。
このように、クラスに整理する作業はコードの可読性と保守性を高めることにつながります。
Pythonのclassの使い方と定義の方法

Pythonでは任意の数のクラスを自由に作れますが、そのための書き方や使い方のルールがあります。クラスの定義内容には次の要素が含まれます。
- クラス名
- 属性(変数)
- メソッド
クラスはテンプレートのような役割で、その中にはどのような機能を持つか、どんな状態を保持しておくかなどの仕様を決めていきます。クラス内の要素によって機能の仕様を表せますが、実際に定義した内容を処理するにはインスタンス化と呼ばれる操作が必要となります。
以降では、クラスの定義と参照方法を実際のコードとともに紹介していきます。
基本的なクラス作成をする
クラスを作るときは、classキーワードに続けてその名前を記述します。下記はSampleClassという名前を持つ空のクラスです。
def __init__(self):
pass
クラス名にはアッパーキャメルケースと呼ばれる、各単語の先頭を大文字で表すのが慣習です。また、クラスの内容を定義していくときはインデントを下げて記述しなければ構文エラーになるため注意しましょう。
def __init__はコンストラクタと呼ばれるメソッドの1種で、最初に実行されることから初期化処理によく使われます。クラスを作っただけでは動かすことができないため、下記のようなインスタンス化と呼ばれる操作を行います。
clsという変数にインスタンスが代入され、コンストラクタの処理が実行されます。この変数を通じて属性やメソッドにアクセスできるようになりますし、変数名を変えればいくつでも生成できますので、状態の異なるパターンを作り出せます。
なお、インスタンスを作らずにクラスから直接アクセスする方法もありますが、以降の節で紹介していきます。
属性を追加する
クラスには物事の状態を表したり、計算結果を保持したりするための変数を定義できます。その変数は属性と呼ばれ、名前と初期値のセットで記述し、変数宣言のように文字列や数値、論理値、タプルなどの値を持たせることができます。
def __init__(self):
self.prop = “属性1”
上記の3行目にあるselfはクラス内でインスタンスを扱うための変数で、そのあとに続く名前が属性名となります。上記のprop属性は、コンストラクタの実行時に初期化されてアクセスできるようになります。
属性の参照は下記のように行います。
print(cls.prop) # 「属性1」が出力される
cls.prop = “値の変更”
print(cls.prop) # 「値の変更」が出力される
属性は変数のように値を参照できますし、値を代入することもできます。
一方で、下記のようにselfを通さずに記述するとクラスに内包されるため、クラス名につなげて属性名を書くことでアクセスができるようになります。
prop2 = “属性2”
なお、クラスに内包された属性はインスタンスからも参照が可能で、値が共有されます。値の参照先は同じであるため、どちらか一方から値が変更されても同じ値が参照されることになります。
メソッドの種類を使い分ける
クラスには具体的な処理を担うメソッドを定義できます。メソッドは任意の引数を受け取り、呼び出し元に処理結果を返す関数であり、呼び出し側から任意のタイミングで実行可能です。
先述のコンストラクタもメソッドの1種でありインスタンスを生成したときに呼び出されます。
メソッドの定義と呼び出しを行うには下記のように記述します。
class SampleClass:
def func(self, val):
return val
cls = SampleClass()
print(cls.func(“実行結果”)) # 「実行結果」が出力される
また、メソッド名に先頭にアンダースコアを2つ付けると、インスタンスからのアクセスを制限することが可能です。外部から属性やメソッドに対して必要以上にアクセスさせないようにすることで、想定外の影響が及ぶことを防げます。
なお、他のプログラミング言語と同じように、クラス外からの利用を禁止することを表明するために慣習的にアンダースコアを1つ付ける方法も採られています。
継承の使用
既存のクラスが持つ属性やメソッドを引き継いだ新しいクラスを継承という方法で作れます。継承を使うと、元のクラスを書き換えずにメソッドを追加、修正できるので、既存のコードに影響を及ぼすことなく容易に機能を拡張できます。
例えばSampleClassを継承するときは、下記のように継承元のクラス名を括弧内に入れて記述します。
class SampleClass:
def func(self, val):
return val
class ExtendedClass(SampleClass):
def func2(self, num):
return num * 2
cls = ExtendedClass()
print(cls.func2(1)) # 「2」が出力される
print(cls.func(1)) # 「1」が出力される
継承先のクラスでは継承元のメソッドが暗黙的に定義されているので、内容を改めて定義することなく継承先クラスのインスタンスからのアクセスが可能になります。
継承は似たようなクラスを作るときや機能を追加するときに有用な機能です。
プロパティの使用
クラスの中で状態や計算結果などを保持するための方法として、属性を用いる以外にもメソッドで定義する方法があります。メソッドに@propertyキーワードを付加することで、属性に直接アクセスすることなく値の参照が可能です。
class SampleClass:
def __init__(self, val):
self.__val = val
@property
def val(self):
return self.__val + “(プロパティ経由)”
@val.setter
def val(self, val):
self.__val = val
cls = SampleClass(“初期値”)
cls.val = “更新値”
print(cls.val) # 「更新値(プロパティ経由)」が出力される
ただし、@propertyの効果は値を参照する用途に限られるので、値を書き換えるには別のプロパティの定義が必要です。
@プロパティ名.setterキーワードを付加すると、同じプロパティに対して値を変更する機能を持たせることができます。
上記のコードではメソッドであるように見えますが、呼び出すときは丸括弧や引数が不要です。属性をそのまま扱う場合と違って、属性を加工した後の値を出力することが可能です。
Pythonのclassにおける引数の種類

Pythonで使うメソッドの引数にはいくつかの種類が存在します。通常の引数はメソッドの呼び出し時に必ず指定しなければならず、定義した個数と順序を合わせる必要があります。
一方、指定しなくてもよいケースや任意の個数を受け取るようなケースの引数も存在しますので、用途に応じて使い分けが必要です。
- デフォルト引数
- 可変長引数
また、メソッドの呼び出し方の違いによる使い分けもあります。
- キーワード引数
引数の特徴を理解して活用することで、よりきれいなコードを書けることにもつながります。以降では、引数の種類の特徴を紹介していきます。
通常の引数(必須引数)
メソッドの引数には任意の数の変数名を指定できます。引数を指定した場合、呼び出し側でもその順番と個数が合うように記述しなければなりません。
class SampleClass:
def func(self, arg1, arg2):
print(arg1, arg2)
cls = SampleClass()
cls.func(“1番目”, “2番目”) # 「1番目」、「2番目」が出力される
なお、メソッドの定義の第1引数にあるselfはクラス内で扱うインスタンスを示す変数なので、呼び出し側で指定する必要はありません。2番目以降の引数を呼び出し側で指定することになる上に、使用するデータ型を間違わないように注意しましょう。
デフォルト引数
メソッドの引数には必ず値を指定しなければなりませんが、デフォルト引数を定義すると指定を省略できます。デフォルト引数は下記のように変数名と初期値をセットで定義します。
class SampleClass:
def func(self, arg=1):
print(arg)
cls = SampleClass()
cls.func() # 「1」が出力される
メソッドを呼び出すときに引数を省略すると変数には初期値が使われ、引数が指定されるとその値が使用されます。
デフォルト引数は、初期値を使うケースと例外的な任意の値を使うケースに分かれるときに使用されます。例えば、税込価格の計算においては基本的に消費税10%で算出しますが、軽減税率の対象になる場合は8%を使用するでしょう。
可変長引数(*args)
メソッドの引数は、クラスで定義する側と呼び出し側とで個数を合わせなければなりませんが、可変長引数を使うと任意の個数の引数で呼び出すことが可能です。可変長引数を定義するには引数の前にアスタリスクを付けて、呼び出し側では1つ以上の値を指定します。
class SampleClass:
def func(self, *arg):
print(arg)
cls = SampleClass()
cls.func(1, 2, 3, 4) # 「(1, 2, 3, 4)」が出力される
可変長引数は、メソッドの中ではタプルという配列データとして扱われます。そのため、メソッドに渡したい値の個数が定まらないときに活用できる機能です。
なお、可変長引数の他にも引数を定義したい場合は、対応する値が明確になるように順序などに注意しましょう。
キーワード引数(**kwargs)
キーワード引数は、対応する引数をメソッド呼び出し時に明示できる機能です。例えば下記のように、メソッドを呼び出すときに値と対応する引数名を一緒に指定します。
class SampleClass:
def func(self, arg1, arg2):
print(arg1, arg2)
cls = SampleClass()
cls.func(arg2=2, arg1=1) # 「1, 2」が出力される
キーワード引数を使用することで、引数に割り当てる値の順番を気にする必要がなくなるため、バグを防ぐことにもつながります。
例えば、同じデータ型の引数が連続して間違いやすかったり、定義されている引数の個数が多かったり、デフォルト引数が混在していたりすると、キーワード引数で指定したほうがコードが読みやすくなるでしょう。
PythonのClassを使う理由

Pythonのコードをクラスに整理する作業は、単に動作させたいのであれば必須ではありませんが、多くのメリットが生まれるため活用したほうが良いでしょう。
人間が直感的に理解できるようにクラスに置き換えることで、全体の構造が明確になり読みやすくできるためプログラム全体の品質向上につながります。その結果、コードがシンプルになり修正や機能拡張が行いやすくなります。
以降では、クラスを使うことによるメリットを解説していきます。
コードの整理がしやすいため
プログラムの規模が大きくなるとコードが段々と複雑化して行数も増えていきますので、全体を見通しにくくなります。膨らんだコードに対して関数化することでも、ある程度処理をまとめることができ、重複した手続きを整理することはできます。
ただし、変数や関数が増えていくと全体の把握が難しくなり、単純に羅列するだけではコードの整理にも限界があるでしょう。例えていえば、本棚を使わず床に本を積み上げている状態に似ています。
一方でクラスを使うと、実装する機能や役割など開発者の認識しやすいレベルでコードを落とし込むことが可能です。クラスは小さな機能に集約できるため、クラス同士の関係さえ明確化されていれば開発者が理解しやすく、管理も行き届きやすくなります。
データと機能をまとめられるため
オブジェクト指向プログラミングでは、プログラムの機能を抽象的な物事に置き換えて、物事とそれらの関係性をクラスで表現していきます。この表現したい物事を、その属性やメソッドとともにコードの中で当てはめていきます。
例えば、ECサイトのショッピングカートをクラスで実装することを考えてみましょう。
カートの中身である商品の情報を属性、それらの商品の操作をメソッドに当てはめてみます。カートの商品を清算する場合、属性である数量や価格をもって支払金額をメソッド内で計算しますが、カートの外から見ると内部でどのように処理されているかを知る必要はありません。
このように、クラスの外に知らせる必要のないことを内部に閉じ込めておくと、外からは簡潔に見えるためコードがシンプルになります。また、カートに機能を追加したいときはクラスの内部を変更すればよいので、変更箇所の把握もしやすいです。
コードの再利用が簡単なため
クラスに整理することでコード全体が見通しやすくなりますが、再利用できるように調整することでさらにコードを効率化できます。
アプリケーションの規模が大きくなってくると似たような処理が繰り返し出てきますが、それらを汎用的なクラスに落とし込むことで、冗長的なコードを取り除くことが可能です。
また、既存のクラスを継承して新しいクラスを作ることも可能です。
継承を利用することで、重複した内容を改めて書くことなく安全に機能を拡張できます。ただし、考えなしにクラスの継承を続けると階層が深くなり複雑化するため、アプリケーションの設計段階で必要なクラスを洗い出しておくことが肝要です。
保守・修正が楽なため
クラスを適切なサイズに分割していくと、修正における影響範囲を小さくできるメリットがあります。
役割がはっきりとしたクラスに上手く分割できると、クラス間の関係や構造がシンプルになり、規模が大きくなっても理解しやすく拡張性の高いコードを保つことができます。
処理内容が冗長で長くなりすぎたコードは、一見しただけでは理解しにくく、紐解いていくのにも時間が掛かります。その結果、修正するたびに改修コストがかさんでいきます。修正に必要な箇所が少なくなれば、素早くリリースできますし、それだけ改修コストも下がります。
また、プログラムが今後拡張されていくことを見越してクラスを作成しておくことも、保守性を高める有効な手段です。
チーム開発が効率化するため
プログラムの開発はチームで行うことが多く、並行して作業するときにコードがクラスで分割されていると取り組みやすいです。1人だけの開発であれば好きに進められますが、複数人の共同作業ではお互いの変更箇所が被らないように配慮されます。
極端にいえば、1つの巨大なPythonファイルを同時に修正しようとするときに上手くいかないことは想像に難くないでしょう。
一方で、クラスを基本単位として設計されたプログラムでは、同じファイルの同時修正を避けることができ、作業分担が行いやすいです。
もし修正ファイルが重複したとしても、メソッドを追加したり継承したりして既存の処理を変更せずに修正もできるため、整理されていないコードに比べて影響範囲は小さくて済むはずです。
クラスとインスタンス、コンストラクタの違い

クラスに関連する概念は他のプログラミング言語でも登場しますが、なじみのない用語が多いため初めて学ぶ方にとっては違いが理解しにくいかもしれません。
下記の表はクラスに関連する用語の違いを示したものです。
| 特徴 | クラス | インスタンス | コンストラクタ |
| 用途 | 新しい型を作るためのテンプレート | クラスを扱えるようにするために、変数に代入されて使用される | インスタンス生成時に実行される |
| 構文 | class クラス名: | cls = クラス名() | def __init__(): |
| 継承 | 他のクラスから継承可能 | ― | 単独での継承は不可 継承先クラスに引き継がれる |
| 属性 | クラス変数とインスタンス変数を持てる | インスタンス変数を参照できる | ― |
| メソッド | 自身の中で定義できる | クラスのメソッドを呼び出せる | 自身がメソッドの1種 ※内部にメソッドを持つことも可能 |
インスタンスはクラスの定義に基づいて生成されるもので、クラスが持つ属性やメソッドにアクセスするために使用されます。
クラスはいわばテンプレートのような役割を持ち、インスタンスにはそのテンプレートに基づいて具体的なデータが作られます。
一方、インスタンスを作るときに呼び出されるのがコンストラクタというメソッドで、準備や初期化処理として使われます。
まとめ:Python Classとは「もの」を作るためのテンプレート

Pythonにおいてclass(クラス)は、コードの可読性を高めて再利用性と保守性を向上させる重要な概念です。
クラスは元々オブジェクト指向プログラミングの根幹となる概念で、物事の状態や動作を表現するのに使われますが、Pythonの中でクラスを使うことは変数やメソッドを使って物事をテンプレートで表すことに相当します。
クラスを使って人間が理解しやすいレベルにコードを改めることで、他の開発者も理解しやすく改修に掛かるコストも抑えられます。
Pythonを学ぶ上で非常に重要な概念なので、クラスの仕組みやメリットを理解して効率的なコーディングに向けて活用していきましょう。
Jiteraでは、要件定義を書くだけでAIが生成するツールでアプリ・システム開発を行っていますので、開発に関するご相談がございましたら、ぜひお気軽にお問い合わせください。

