閉じる

Python入門: クラスからインスタンスを生成するやり方

Pythonで独自のデータ型(クラス)から実体(インスタンス)を作る最初の一歩を、最小の例から丁寧に確認します。

ポイントは、クラス名の後ろに必ず丸かっこを付けて呼び出すこと、そしてPythonではnewを使わないという2点です。

最後に、複数生成や呼び出し忘れなどのよくあるミスも避けられるように整理します。

クラスからインスタンスを生成する基本

クラスとインスタンスの違い

クラスは「設計図」、インスタンスはその設計図から作られる「具体物」です。

クラスはデータの形や振る舞いの定義を持ち、インスタンスは定義どおりに作られた実体としてメモリ上に存在します。

まずはクラスを定義し、そのクラスを呼び出すことでインスタンスを作成します

次の表は要点の対比です。

観点クラスインスタンス
役割設計図設計図から生成された実体
生成方法定義する(class文)ClassName()を呼ぶ
個数1つの定義で良い必要な数だけ作れる
使い道仕様をまとめる実際のデータを扱う

書き方は ClassName() を呼ぶ

インスタンス生成はClassName()のように、関数呼び出しと同じ書き方です。

丸かっこを付けないClassNameは「クラスそのもの」(設計図)を指すだけで、インスタンスは作られません。

Pythonはnew不要(コンストラクタは関数呼び出しで実行)

他言語ではnewを使うことがありますが、Pythonではnewは不要です。

インスタンス生成時に、初期化用メソッド__init__があれば自動的に呼ばれます。

つまり、関数呼び出しと同時にコンストラクタが実行されると理解してください。

最小の例で学ぶインスタンス作成

空のクラス定義(class Foo)

最小のクラスは、何も中身を持たないクラスです。

キーワードpassで空の定義にします。

Python
# 最小のクラス定義
class Foo:
    # まだ属性やメソッドは何も定義しない
    # とりあえず、空のクラスとして定義する
    pass

インスタンスを変数に代入する

クラスFooからインスタンスを1つ作成し、変数に入れます。

Python
class Foo:
    pass

# インスタンスを生成して変数に代入
foo = Foo()  # 丸かっこ()が重要。これで「呼び出し=生成」になる

この時点でメモリ上にFoo型の実体が1つ生まれ、変数fooがそれを参照します。

printで生成結果を確認する

printでインスタンスを表示すると、デフォルトではクラス名と場所の情報が表示されます。

より確実に型を確認するにはtypeisinstanceも使えます。

Python
class Foo:
    pass

foo = Foo()

# 生成結果の確認
print(foo)                     # デフォルト表示(例: <__main__.Foo object at 0x...>)
print(type(foo))               # 型情報(例: <class '__main__.Foo'>)
print(type(foo).__name__)      # 型名だけを取り出す(Foo)
print(isinstance(foo, Foo))    # fooがFooのインスタンスかどうか(True)
実行結果
<__main__.Foo object at 0x...>
<class '__main__.Foo'>
Foo
True

表示のアドレス部分(0x以降)は毎回変わるため、同一性の確認にはis演算子やid関数を使います。

引数つきのインスタンス生成(概要)

ClassName(引数)で初期化を同時に行う

初期化パラメータが必要な場合は、__init__で受け取り、生成時にClassName(引数)で渡します。

これは関数呼び出しと同じ感覚です。

Python
# 座標点を表す最小のクラス
class Point:
    def __init__(self, x, y):
        # 生成直後にxとyを設定(初期化)
        self.x = x
        self.y = y

# 生成と同時に初期化
p = Point(3, 4)

print(p.x, p.y)  # xとyが設定されていることを確認
実行結果
3 4

ここでselfは「自分自身のインスタンス」を受け取る引数であり、呼び出し側で渡す必要はありません。

呼び出し側はPoint(3, 4)の2つだけ渡します。

引数が合わないとTypeErrorになる

引数の個数や名前が一致しないとTypeErrorが発生します。

原因を読み取り、指定すべき引数をそろえて再実行します。

Python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

# 引数が1つ足りない呼び出し(間違い)
p = Point(3)
実行結果
Traceback (most recent call last):
  ...
TypeError: Point.__init__() missing 1 required positional argument: 'y'

エラーメッセージは修正のヒントです。

上の例ではyが不足していることが明確に示されています。

複数生成とよくあるミス

複数インスタンスは独立して存在する

同じクラスから何個でも独立したインスタンスを作れます。

それぞれは別の実体なので、同じクラスでも同一ではありません。

Python
class Foo:
    pass

a = Foo()
b = Foo()

print(a is b)       # 同一オブジェクトか(物理的に同じか) -> False
print(id(a), id(b)) # 参照先が異なることを数値IDで確認
実行結果
False
123456789 123456999

数値IDは実行ごとに異なりますが、a is bFalseである点が重要です。

リストや辞書に複数のオブジェクトを保存する

インスタンスはリストや辞書にそのまま保存できます。

必要に応じて取り出し、処理できます。

Python
class User:
    def __init__(self, name):
        self.name = name

users = [User("Alice"), User("Bob"), User("Carol")]

# リストから取り出して使う
for u in users:
    print(u.name)

# 辞書で名前→インスタンスのマップを作る
user_map = {u.name: u for u in users}
print("Carol" in user_map)  # キーの存在確認
print(user_map["Bob"].name) # Bobのインスタンスにアクセス
実行結果
Alice
Bob
Carol
True
Bob

1つのクラス定義から必要なだけインスタンスを作り、コレクションに保持できることを押さえましょう。

呼び出し忘れに注意(ClassName ではなく ClassName() を使用)

初心者が最もやりがちなミスは、丸かっこを付け忘れることです。

ClassNameはクラスそのもので、インスタンスではありません

Python
class Foo:
    pass

obj = Foo      # ← 呼び出していない(間違い)。これは「クラス」を代入しているだけ
print(type(obj))          # type型(メタクラス)のオブジェクト=クラスであることが分かる
print(callable(obj))      # クラスは呼び出し可能(=これから生成できる設計図)
# print(obj.some_attr)    # ここで属性に触ろうとすると、多くの場合エラーにつながる
実行結果
<class 'type'>
True

正しくはFoo()と呼び出して生成します。

Python
obj = Foo()    # ← 正しい。ここでインスタンスが生成される
print(isinstance(obj, Foo))
実行結果
True

見た目は似ていますがFooFoo()は根本的に違う点を、常に意識してください。

まとめ

本記事では、クラスからインスタンス(オブジェクト)を生成する最小限の基礎を確認しました。

ポイントは次のとおりです。

クラスは設計図、インスタンスは実体であり、生成はClassName()を呼ぶだけです。

Pythonではnewは不要で、初期化が必要なら__init__で引数を受け取ります。

複数インスタンスは互いに独立し、リストや辞書に自由に格納できます。

最後に、丸かっこ忘れ(クラスそのものを代入してしまうミス)に注意しましょう。

これらを押さえれば、以降の属性やメソッド、特殊メソッドの学習へスムーズに進めます。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!