| この記事の要点 |
|
__init__ が初期化を担当する
class User:
def __init__(self, name, age=0):
self.name = name
self.age = age
print("初期化されました")
u = User("田中", 30) # 初期化されました
print(u.name, u.age) # 田中 30
User("田中", 30) と書いたとき、Python は内部で次の順に処理しています。
| 順 | 呼ばれるもの | 役割 | 戻り値 |
|---|---|---|---|
| 1 | __new__(cls, ...) | インスタンスを作る | 作ったインスタンス |
| 2 | __init__(self, ...) | 作られたものを初期化する | None でなければならない |
__init__ で return に値を書くと TypeError: __init__() should return None になります。「戻り値を返すコンストラクタ」を作りたい場合は次の @classmethod を使います。
オーバーロードはできない
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __init__(self, text): # ← 上書きされる。エラーにもならない
self.x, self.y = map(int, text.split(","))
Point(1, 2) # TypeError: __init__() takes 2 positional arguments but 3 were given
Python の関数定義は名前への代入なので、同名で 2 回書くと後の定義だけが残ります。引数の数や型で切り替える仕組みはありません。
方法 1: デフォルト引数でまとめる
class Point:
def __init__(self, x=0, y=0):
self.x, self.y = x, y
Point() # (0, 0)
Point(1) # (1, 0)
Point(1, 2) # (1, 2)
Point(y=5) # (0, 5) キーワード指定もできる
方法 2: classmethod のファクトリ(推奨)
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
@classmethod
def from_text(cls, text): # "1,2" から作る
x, y = map(int, text.split(","))
return cls(x, y)
@classmethod
def origin(cls): # 原点を作る
return cls(0, 0)
p1 = Point(1, 2)
p2 = Point.from_text("3,4")
p3 = Point.origin()
作り方ごとに名前が付くため、どの生成方法なのかが呼び出し側で一目で分かります。cls(...) と書いておけば、継承したクラスから呼んでも正しく子クラスのインスタンスが返ります。
継承したら super().__init__() を呼ぶ
class User:
def __init__(self, name):
self.name = name
class Admin(User):
def __init__(self, name, level):
super().__init__(name) # ← これが無いと self.name が作られない
self.level = level
a = Admin("田中", 3)
print(a.name, a.level) # 田中 3
class Broken(User):
def __init__(self, name, level):
self.level = level # super() を呼び忘れた
b = Broken("田中", 3)
print(b.name) # AttributeError: 'Broken' object has no attribute 'name'
子クラスで __init__ を定義しなければ、親の __init__ がそのまま使われます。定義した瞬間に親の初期化は行われなくなるので、super().__init__() の呼び忘れが最頻出のバグです。
__new__ を使う場面
__new__ を書く必要があるのは、イミュータブルな型を継承したときと生成そのものを制御したいときだけです。
class UpperStr(str): # str は生成後に中身を変えられない
def __new__(cls, value):
return super().__new__(cls, value.upper())
print(UpperStr("abc")) # ABC
# シングルトン(常に同じ 1 個を返す)
class Config:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
print(Config() is Config()) # True
__new__ がそのクラスのインスタンス以外を返すと __init__ は呼ばれません。シングルトンでは __init__ が生成のたびに走る点にも注意が必要です(初期化済みフラグを持たせるか、__init__ を空にします)。
データの入れ物なら dataclass
from dataclasses import dataclass, field
@dataclass
class User:
name: str
age: int = 0
tags: list[str] = field(default_factory=list) # 可変な既定値はこう書く
def __post_init__(self): # __init__ の直後に呼ばれる
if self.age < 0:
raise ValueError("age は 0 以上にしてください")
u = User("田中", 30)
print(u) # User(name='田中', age=30, tags=[])
__init__ / __repr__ / __eq__ が自動生成されます。属性を並べるだけの __init__ を書いているなら @dataclass にできます。
なお tags: list[str] = [] と書くと ValueError: mutable default で弾かれます。dataclass は 変数 で説明した「デフォルト引数の共有」問題を防ぐため、default_factory を強制します。
デストラクタ(__del__)は当てにしない
class Handle:
def __del__(self):
print("破棄") # いつ呼ばれるか保証がない
# 後始末は with 文で明示する
class Handle:
def __enter__(self):
print("開く")
return self
def __exit__(self, exc_type, exc, tb):
print("閉じる") # 例外が起きても必ず呼ばれる
with Handle():
print("処理中")
ファイルや接続の解放は __del__ ではなく with 文(コンテキストマネージャ)で行います。
関連
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38