Pythonでクラスを学び始めると、必ず登場するのがselfです。
多くの人が「thisと何が違うのか」「なぜ毎回書くのか」と疑問を持ちます。
本記事では、selfの基本から実践的な使い方、他言語との違いまでを、初心者の方にも分かりやすいように丁寧に解説していきます。
Pythonのselfとは何か
selfの基本的な意味と役割

Pythonのselfは、「メソッドの中で、今まさに操作しているインスタンス(オブジェクト)そのものを指す変数」です。
クラスのメソッドを呼び出すと、そのメソッドの第1引数として、呼び出し元のインスタンスが自動的に渡されます。
このインスタンスを受け取るための名前として、慣習的にselfが使われています。
ポイントを整理すると、selfには次のような役割があります。
- メソッドの中からインスタンス変数(属性)やインスタンスメソッドへアクセスするための窓口になること
- 「どのインスタンスに対する処理なのか」を区別するための印として機能すること
つまり、selfはインスタンスとメソッドを結び付ける“のり”のような存在だと考えると理解しやすくなります。
なぜPythonでselfが必要なのか

Pythonでは、メソッドの定義時に「どのインスタンスに対する処理か」を明示的に受け取る必要があります。
これは、Pythonが「暗黙のthis」を持たない設計になっているためです。
JavaやC++などでは、インスタンスメソッドの中でthisが暗黙に使われますが、Pythonではselfを明示的に引数として書くことで、可読性とシンプルさを保っています。
もしselfがなかった場合、メソッドの中から「どのインスタンスの属性を変更しているのか」が曖昧になってしまいます。
selfを最初の引数として受け取ることで、メソッドは常に「自分が操作すべきインスタンス」を正確に知ることができます。
selfとインスタンス(オブジェクト)の関係

selfとインスタンスの関係は、次のように理解できます。
- インスタンスは、クラスを元に作られた実体です。
- メソッドを呼び出すとき、実際には「インスタンス自身」がメソッドに渡されています。
- メソッドの中では、その渡されてきたインスタンスを
selfという名前で受け取り、利用します。
たとえば、次のようなコードを考えてみます。
class Counter:
def __init__(self):
# ここでselfは、生成されつつあるインスタンス自身を指します
self.value = 0
def increment(self):
# ここでもselfは、メソッドを呼んだインスタンスを指します
self.value += 1
c1 = Counter() # インスタンス1
c2 = Counter() # インスタンス2
c1.increment() # ここではincrementのselfはc1
c2.increment() # ここではincrementのselfはc2
上の例では、同じクラス・同じメソッドを使っていますが、selfを通じてそれぞれ別々のインスタンスの状態が管理されています。
これがselfとインスタンスの密接な関係です。
selfの正しい使い方
クラス定義とselfの書き方

Pythonのクラス定義では、インスタンスメソッド(普通のメソッド)の第1引数にselfを書くのが慣習です。
構文上は名前を変えても動作しますが、読みやすさ・統一性のために必ずselfを使うと考えておくとよいです。
class User:
# インスタンスメソッドの定義。第1引数はselfにするのが慣例。
def greet(self, name):
# selfは、このメソッドを呼び出したインスタンス自身
print(f"こんにちは、{name}さん。私はUserインスタンスです。")
このように、クラス内でdefを使ってメソッドを定義する際には、必ず第1引数にselfを書くと覚えておきましょう。
コンストラクタ(__init__)とselfの使い方

__init__は、インスタンスが生成された直後に呼び出されるコンストラクタです。
ここでも最初の引数としてselfを受け取ります。
selfが、新しく作られたインスタンスを指していると考えてください。
class User:
def __init__(self, name, age):
# ここでselfは、新しく作られたUserインスタンス
# self.nameやself.ageとしてインスタンス変数を定義します
self.name = name
self.age = age
def show_info(self):
# __init__で設定したインスタンス変数にアクセス
print(f"名前: {self.name}, 年齢: {self.age}")
# インスタンス生成時に__init__が自動で呼ばれる
user1 = User("太郎", 20)
user1.show_info()
名前: 太郎, 年齢: 20
このように、コンストラクタではselfを使って初期状態(属性)を設定するのが基本的なパターンです。
インスタンスメソッドとselfの書き方

インスタンスメソッドとは、インスタンスに対して呼び出すメソッドです。
クラスの外からインスタンス.メソッド()と呼び出すものがこれに当たります。
class Rectangle:
def __init__(self, width, height):
# selfにインスタンス固有の情報を紐付ける
self.width = width
self.height = height
def area(self):
# selfを通じて自身の属性にアクセス
return self.width * self.height
def show_area(self):
# インスタンスメソッドの中から、別のインスタンスメソッドもself経由で呼び出す
print(f"面積は {self.area()} です。")
rect = Rectangle(3, 4)
rect.show_area() # インスタンスメソッドの呼び出し
面積は 12 です。
インスタンスメソッドの定義では、第1引数にselfを書き、そのselfを通じてインスタンスの状態を操作するのが基本です。
selfでインスタンス変数(属性)にアクセスする方法

インスタンス変数(属性)とは、各インスタンスが個別に持つデータのことです。
Pythonでは、self.属性名という形でアクセスしたり、定義したりします。
class BankAccount:
def __init__(self, owner, balance):
# ここでself.ownerやself.balanceというインスタンス変数を定義
self.owner = owner
self.balance = balance
def deposit(self, amount):
# インスタンスの残高(self.balance)を更新
self.balance += amount
print(f"{amount}円を入金しました。現在の残高: {self.balance}円")
def withdraw(self, amount):
if amount > self.balance:
print("残高不足です。")
else:
self.balance -= amount
print(f"{amount}円を出金しました。現在の残高: {self.balance}円")
account = BankAccount("花子", 1000)
account.deposit(500)
account.withdraw(300)
500円を入金しました。現在の残高: 1500円
300円を出金しました。現在の残高: 1200円
ここで重要なのは、クラスの外からはaccount.balanceと書くのに対して、クラスの中からはself.balanceと書くという点です。
クラスの中で、インスタンスの属性に触るときは必ずself.を付けると覚えておきましょう。
selfを付けるべき場面・付けてはいけない場面

selfは何でもかんでも付けてよいわけではなく、付けるべき場所と付けてはいけない場所があります。
付けるべき場所は、主に次の2つです。
1つ目は、インスタンスメソッドの第1引数です。
ここでselfを受け取ることで、メソッドの中でインスタンスにアクセスできるようになります。
2つ目は、インスタンスに紐付いた属性やメソッドにアクセスするときです。
例えばself.nameやself.some_method()のように書きます。
反対に、selfを付けてはいけない主な場所として、次のものがあります。
1つは、クラスの外で定義した変数や関数です。
これらは特定のインスタンスに紐付いていないため、selfを使う対象ではありません。
もう1つは、メソッド内での一時的なローカル変数です。
これらはインスタンスの状態として保持する必要がないので、単にxやresultなどと書けば十分です。
class Example:
def __init__(self, value):
# インスタンスに保持したい値はselfを付ける
self.value = value
def compute_double(self):
# 一時的な値はselfを付ける必要はない
doubled = self.value * 2
return doubled
このように、「インスタンスとして後からも参照したい情報→selfを付ける」「一時的な計算用で、そのメソッド内だけで完結する情報→selfを付けない」という観点で判断すると、混乱しにくくなります。
selfの具体例とよくある疑問
実例で理解するselfの動き

selfの実際の動きを、簡単なゲームのキャラクタークラスで確認してみます。
class Player:
def __init__(self, name, hp):
self.name = name # プレイヤー名
self.hp = hp # 体力
def attack(self, other, damage):
# selfは攻撃する側、otherは攻撃される側
print(f"{self.name}の攻撃! {other.name}に{damage}ダメージ!")
other.hp -= damage
print(f"{other.name}の残りHP: {other.hp}")
def is_alive(self):
return self.hp > 0
# プレイヤーを2人作成
p1 = Player("勇者", 30)
p2 = Player("魔法使い", 20)
# p1がp2を攻撃
p1.attack(p2, 5)
# p2がp1を攻撃
p2.attack(p1, 8)
勇者の攻撃! 魔法使いに5ダメージ!
魔法使いの残りHP: 15
魔法使いの攻撃! 勇者に8ダメージ!
勇者の残りHP: 22
この例では、attackメソッドのselfは、メソッドを呼び出したインスタンスを指しています。
1回目はselfがp1、2回目はselfがp2になります。
同じメソッドでも、呼び出し元のインスタンスによってselfが変わる点に注目してください。
インスタンスメソッド・クラスメソッド・静的メソッドの違い

Pythonには、selfを使うインスタンスメソッドのほかに、クラスメソッドと静的メソッドがあります。
それぞれの違いを整理しておくと、selfの位置づけがよりはっきりします。
インスタンスメソッドは今まで説明してきた通り、第1引数にselfを取り、インスタンスの状態にアクセスするためのメソッドです。
クラスメソッドはクラス自体に紐付くメソッドで、@classmethodデコレータを付け、第1引数としてclsを受け取ります。
ここでclsはクラスオブジェクトを指します。
静的メソッドは、インスタンスやクラスに依存しない汎用的な関数を、クラスの名前空間の中にまとめておくためのものです。
@staticmethodを付け、特にselfやclsのような特別な第1引数を取りません。
具体例で見てみます。
class MathUtil:
def __init__(self, factor):
# インスタンスごとに異なる倍率
self.factor = factor
# インスタンスメソッド: selfを受け取り、インスタンスの状態を利用
def multiply(self, x):
return x * self.factor
# クラスメソッド: clsを受け取り、クラスに対する処理を行う
@classmethod
def from_double(cls):
# factor=2のインスタンスを生成するクラスメソッド
return cls(2)
# 静的メソッド: selfもclsも受け取らない、汎用的な関数
@staticmethod
def add(a, b):
return a + b
# 使い方
m1 = MathUtil(3)
print(m1.multiply(10)) # インスタンスメソッド
m2 = MathUtil.from_double() # クラスメソッドで生成
print(m2.multiply(10))
print(MathUtil.add(5, 7)) # 静的メソッドはクラスから直接呼び出し
30
20
12
ここから分かるように、selfが登場するのはあくまで「インスタンスメソッド」の中だけです。
クラスメソッドではcls、静的メソッドではどちらも受け取りません。
self以外の名前は使えるのか

Pythonの仕様上、第1引数の名前がselfでなければならないというルールはありません。
実際には、次のように書いても動作します。
class Sample:
def show(this, msg):
# ここでthisは、インスタンス自身を指している
print(f"メッセージ: {msg}")
しかし、実務では絶対にやめたほうがよい書き方です。
Pythonコミュニティ全体の慣習として、インスタンスメソッドの第1引数の名前はselfに統一することが事実上のルールになっています。
理由は次の通りです。
1つは、コードを読んだ瞬間に「これはインスタンスメソッドだ」と理解できるからです。
もう1つは、ほとんど全てのPythonの教材・ドキュメント・ライブラリがselfを前提にしているため、統一しておくことが学習面でも保守面でも有利だからです。
そのため、「書けるけれど書いてはいけない」と覚えておくのが実用的です。
selfを省略できない理由

selfは、Pythonのメソッド呼び出しの仕組みの一部なので、省略することはできません。
なぜなら、インスタンス.メソッド()という呼び出しは、内部的にはクラス.メソッド(インスタンス)のように変換されているからです。
具体的には、次の2つはほぼ同じ意味になります。
obj.method(10) # ふつうの書き方
ClassName.method(obj, 10) # 実際の呼び出し方に近いイメージ
このとき、methodの第1引数でインスタンスを受け取る必要があるため、その受け皿としてselfを書く必要があります。
もし定義側でselfを省略すると、引数の数がずれてしまうのです。
class Sample:
# selfを書き忘れた悪い例
def show(msg):
print(msg)
s = Sample()
s.show("hello") # 実際にはSample.show(s, "hello")として呼ばれるイメージ
このコードは、次のようなエラーになります。
TypeError: Sample.show() takes 1 positional argument but 2 were given
これは、定義では1つしか引数を受け取れないのに、呼び出し時にはインスタンス(s)と”hello”の2つが渡されてしまったためです。
このように、selfは単なる名前ではなく、インスタンスを受け取るための必須の引数だと理解してください。
selfに関するよくあるエラーと対処法

selfまわりでは、特に初心者が次のようなエラーに遭遇しがちです。
1つ目は、先ほど見たTypeError: takes 1 positional argument but 2 were givenのようなエラーです。
これはインスタンスメソッドの定義でselfを入れ忘れたときによく起こります。
2つ目は、NameError: name ‘xxx’ is not definedというエラーです。
これは、本来はself.nameのように書くべきところを、誤ってnameだけにしてしまったときなどに発生します。
class Example:
def __init__(self, name):
self.name = name
def show(self):
# 間違い: self.nameではなくnameと書いてしまった
print(name)
この場合、showメソッドの中にnameというローカル変数は存在しないため、NameErrorになります。
対処法はインスタンス変数には必ずself.を付けるというルールを徹底することです。
3つ目は、AttributeErrorに代表される、selfの使い方を混同したときのエラーです。
例えば、クラスメソッドや静的メソッドの中でselfを使おうとしたり、クラスから直接インスタンス変数にアクセスしようとしたりすると発生します。
エラーが出たときは、まず「このメソッドはインスタンスメソッドか、クラスメソッドか、静的メソッドか」を整理し、それに応じてselfやclsの使い方が正しいかを確認すると、原因にたどり着きやすくなります。
Pythonのselfと他言語との違い
PythonのselfとJavaのthisの違い

JavaのthisとPythonのselfは、「そのインスタンス自身を指す」という点では似ていますが、いくつかの重要な違いがあります。
まず、Javaではthisは暗黙の引数であり、メソッド定義のかっこの中に書く必要はありません。
対してPythonでは、selfを明示的に引数として書く必要があることが大きな違いです。
さらに、Javaではフィールド名とローカル変数名がかぶらない限り、this.を省略できることが多いですが、Pythonではインスタンス変数には必ずself.を付けます。
この違いから、Java経験者は最初「なぜ毎回selfを書かなければならないのか」と違和感を覚えやすいですが、Pythonでは明示的で読みやすいことが重視されていると理解すると納得しやすくなります。
PythonのselfとC++のthisポインタの違い

C++では、メンバ関数の中でthisというポインタが暗黙に利用でき、現在のオブジェクトを指します。
Pythonのselfも同様に「現在のインスタンスを指す」という意味を持ちますが、ポインタではなく単なる引数(参照)です。
C++のthisはポインタなのでthis->memberのように書きますが、Pythonではself.memberと書きます。
また、C++ではポインタ演算などの概念がありますが、Pythonのselfではそのような低レベルな操作は行いません。
この違いから、C++経験者はselfを「毎回明示的に受け取るthisポインタのようなもの」として理解するとスムーズです。
内部的には参照の受け渡しですが、ポインタのような複雑さは隠蔽されています。
PythonのselfとJavaScriptのthisの違い

JavaScriptのthisは、呼び出し方や実行コンテキストによって参照先が変わる動的な仕組みを持っており、多くの開発者を悩ませるポイントです。
一方、Pythonのselfは、そのような動的な振る舞いはせず、常に「メソッドを呼び出したインスタンス」を指します。
JavaScriptでは、関数を変数に代入したり、イベントハンドラとして渡したりするとthisの指す先が変わることがありますが、Pythonではselfを明示的に引数として受け取るため、そのような混乱は起こりにくくなっています。
この点で、PythonのselfはJavaScriptのthisよりも予測可能でシンプルだと言えます。
Pythonのselfが初心者に分かりにくい理由と理解のコツ

selfが分かりにくいと感じられる主な理由は、いくつかの誤解や先入観にあります。
多くの初心者の方は、selfを「特別なキーワード」や「言語が用意した魔法の変数」のように捉えがちです。
しかし実際には、selfはただの引数名にすぎません。
理解のコツとしては、次のように考えるとよいです。
1つは、「selfという名前の変数に、インスタンスへの参照が自動で入れられているだけ」というイメージを持つことです。
このとき、obj.method()がClass.method(obj)とほぼ同じ意味になる、というイメージが役に立ちます。
もう1つは、「クラスの外からはobj.x、クラスの中からはself.x」という2視点を意識することです。
外から見れば「インスタンス名.属性」、中から見れば「self.属性」となっているだけで、本質的には同じ対象を指しています。
最後に、selfは予約語ではないが、事実上「必ずselfにする」という約束事だと理解しておくと、他人のコードを読むときの混乱を防げます。
selfはPythonらしい「明示的で読みやすい」設計の一部だと捉えると、違和感が徐々に薄れていくはずです。
まとめ
Pythonのselfは、クラスとインスタンスを理解するための鍵となる概念です。
selfは「メソッドの中で、そのメソッドを呼び出したインスタンス自身を指す変数」であり、インスタンス変数や他のメソッドにアクセスするための窓口として機能します。
selfは予約語ではなく、単なる第1引数名ですが、Pythonの慣習としてselfと書くことが事実上のルールです。
他言語のthisと比較すると、Pythonのselfはより明示的で予測しやすい仕組みになっています。
selfを「インスタンスが自分自身を指すための名前」と捉え、インスタンスメソッドでは必ず第1引数にselfを書く習慣を身につければ、クラス設計やオブジェクト指向プログラミングがぐっと理解しやすくなります。
