Pythonのアンダーバー(アンダースコア)とはなんなのか?
Pythonをブラウザで実行しながら実践的に学ぶ
Pythonの基礎からソフトウェアアーキテクチャ,アルゴリズムなどの応用的な内容まで幅広く学べます。
ブラウザ上で直接Pythonコードを試すことができ、実践的なスキルを身につけることが可能です。
Pythonを学んでいると、変数名や関数名の中に「アンダーバー(_)」を頻繁に見かけます。
たとえば user_name
や _private_var
、さらには __init__
のように複数並んでいる場合もあります。
「なんとなく付けているように見えるけど、意味があるの?」 「1つと2つのアンダーバーでは何が違うの?」
このような疑問を持つ初心者はとても多いです。実際、Pythonのアンダーバーには文法的な意味を持つものから慣習的なサインまで、さまざまな役割があります。
この記事では、Pythonのアンダーバーを位置・個数ごとに詳しく解説し、実際のサンプルコードを交えてその使い方と意図を理解できるように説明します。 読み終わる頃には、あなたのコードにもPythonらしい美しさが理解できるはずです。
アンダーバー(_)とは?基本の意味をおさらい¶
アンダーバー(underscore)とは、「_」という記号のことです。 Pythonではスペースを使えないため、単語を区切るための記号として使われます。
user_name = "Tanaka"
login_count = 3
このように、user_name
のように単語の間に _
を入れることで、読みやすい変数名を作ることができます
Pythonでは「スネークケース(snake_case)」という命名規則が推奨されており、アンダーバーはその中で最も基本的な記号です。
しかし、Pythonではそれだけではありません。
アンダーバーは「単体」「先頭」「末尾」「両端」によって特別な意味を持つ場合があり、プログラムの意図を伝える重要なサインになります。 それぞれについて詳しく解説していきます。
アンダーバーの使い方と意味のまとめ¶
まずは全体像をつかみましょう。 Pythonでは、アンダーバーの使い方によって次のような違いがあります。
形式 | 主な用途 | 意味・目的 |
---|---|---|
_ (単体) |
一時変数、使わない値、REPLの結果保持 | 値を無視したいときに使う |
_var (先頭に1つ) |
慣習的な非公開変数 | 外部から直接アクセスしないことを示す |
__var (先頭に2つ) |
名前マングリング(内部専用) | クラス外・サブクラスからアクセスされにくくする |
__var__ (前後に2つ) |
マジックメソッド(特殊メソッド) | Pythonの内部動作を拡張する |
var_ (末尾に1つ) |
予約語との衝突回避 | 命名の競合を防ぐ |
一見すると同じような _
ですが、実際には全く異なる役割を果たしています。
ここからは、1つずつ詳しく見ていきましょう。
_
(アンダーバー単体)|使わない値を無視するときに使う¶
まずは最もシンプルな使い方、単体のアンダーバーです。 これは「この値は使わない」ことを明示的に表します。
以下のサンプルコードを見てみましょう。
for _ in range(5):
print("Hello, Python!")
このコードでは、ループ変数の値を実際には使っていません。
そのため、変数名をi
などにせず「_」を使うことで、「値自体には興味がない」という意図を伝えています。
出力結果は以下のようになります。
Hello, Python!
Hello, Python!
Hello, Python!
Hello, Python!
Hello, Python!
このように、値を無視したいときにアンダーバーを使うのがPythonの慣習です。 タプルやリストを分解(アンパック)するとき、使わない値をアンダーバーで受け取ることもできます。
user = ("Tanaka", 28, "Tokyo")
name, _, city = user
print(name, city)
# 出力: Tanaka Tokyo
_
を使うことで、「年齢の情報は使わない」という意図を明確にできます。
こうした小さな工夫が、読みやすくバグを生みにくいコードにつながります。
REPLでの「_」|最後の計算結果を保持する¶
Pythonの対話モード(REPL)では、アンダーバーが直前の計算結果を自動で保持します。
>>> 3 + 5
8
>>> _ * 2
16
このように、REPLではアンダーバーを使うと直前の結果にアクセスできるという便利な機能があります。 ただし、スクリプトファイルで使ってもこの挙動は起きません。 つまり、REPL専用の特性であることを覚えておきましょう。
_var
(先頭に1つ)|「外部から触らないで」を意味する慣習¶
クラス内で変数やメソッド名の先頭にアンダーバーを1つ付けると、「この変数は内部用です。外から直接触らないでください」という意図を伝えることができます。
以下のサンプルコードを見てみましょう。
class User:
def __init__(self, name):
self._password = "secret"
user = User("Tanaka")
print(user._password)
実はこのコード、実行すれば動きます。 PythonにはC++やJavaのような「private」キーワードがないため、あくまで慣習で非公開を示しているのです。
なぜ「慣習」なのか?¶
Pythonの哲学には、We are all consenting adults here(私たちは皆、分別ある大人だ)という考えがあります。
つまり、アクセスできても、しない方が良いことを分かっている前提なのです。
そのため、_
で始まる変数を見たら「内部用だな」と判断するのがPythonの作法です。
__var
(先頭に2つ)|名前マングリングで外部アクセスを防ぐ¶
次に、アンダーバーが2つ付くパターンを見てみましょう。 これは名前マングリング(name mangling)と呼ばれ、クラス内部専用の変数を作るときに使われます。
class Account:
def __init__(self, balance):
self.__balance = balance
account = Account(1000)
print(account.__balance) # エラーになる
このコードを実行すると、AttributeError
が発生します。
なぜなら、Pythonが内部的に変数名を変えて隠しているからです。
print(account._Account__balance)
# 出力: 1000
このように、実際には _Account__balance
という名前に変換されています。
つまり「完全な非公開」ではありませんが、意図しないアクセスを防ぐ効果があります。
サブクラスで同名の変数を誤って上書きしてしまうのも防げるため、安全性を高めたい場合に有効です。
__var__
(前後に2つ)|マジックメソッド(特殊メソッド)¶
Pythonで最も有名なアンダーバーの使い方がこれです。
__init__
や__str__
など、両端に2つのアンダーバーが付くメソッドはマジックメソッドと呼ばれます。
これらは、Pythonの内部挙動をカスタマイズするための特別な関数です。
class Book:
def __init__(self, title):
self.title = title
def __str__(self):
return f"『{self.title}』という本です。"
book = Book("Python入門")
print(book)
出力結果は以下のようになります。
『Python入門』という本です。
通常、オブジェクトをprintすると「<main.Book object at 〜>」のように表示されますが、 __str__
を定義しておくことで、人が読みやすい形式に変更できます。
他にも、さまざまなマジックメソッドがあります。
メソッド名 | 役割 |
---|---|
__init__ |
コンストラクタ(初期化時に呼ばれる) |
__str__ |
print()時の文字列表現を定義 |
__len__ |
len()の結果を定義 |
__getitem__ |
インデックスアクセスを定義 |
__add__ |
+演算子の挙動を定義 |
こうしたマジックメソッドを理解すると、Pythonの「オブジェクト指向的な柔軟さ」を活かせるようになります。
var_
(末尾に1つ)|予約語との衝突を防ぐ¶
Pythonには「class」や「def」などの予約語が多数存在します。 それらと変数名が被ってしまう場合は、末尾にアンダーバーをつけて避けます。
class_ = "Engineer"
def_ = "create_function"
print(class_)
このようにすることで、予約語を避けつつ意味のわかりやすい名前を維持できます。
class
という単語を変数として使いたいときは、この方法が定番です。
_
は遅い?パフォーマンスへの影響を検証¶
「アンダーバーを使うと遅くなる」と聞いたことがあるかもしれません。
結論から言えば、ほとんどの場合で影響はありません。
ただし、REPLでは直前の結果を_
に保存するため、微小なオーバーヘッドが発生することはあります。
以下のコードで簡単に検証してみましょう。
import time
def use_underscore():
for _ in range(10_000_000):
pass
def use_variable():
for i in range(10_000_000):
pass
start = time.time()
use_underscore()
print("underscore:", time.time() - start)
start = time.time()
use_variable()
print("variable:", time.time() - start)
実行してみると、ほとんど同じ結果になります。
つまり、「アンダーバーを使うと遅くなる」というのは誤解です。 むしろ、コードの意図を明確にするために積極的に使うべきです。
実務でのアンダーバー利用例|チーム開発での命名規則¶
実際のプロジェクトコードでも、アンダーバーはあらゆる場面で使われます。
たとえば次のようなクラス構成を考えてみましょう。
class _DatabaseConnector:
def __init__(self, db_name):
self._db_name = db_name
def _connect(self):
print(f"{self._db_name} に接続中...")
class UserRepository(_DatabaseConnector):
def __init__(self):
super().__init__("user_db")
def save_user(self, user_name):
self._connect()
print(f"{user_name} を保存しました。")
ここでは、_DatabaseConnector
や _connect()
にアンダーバーが使われています。
これらは「外部のモジュールから直接呼び出すことを想定していない」ことを意味します。
チームでコードを書く場合、こうした命名ルールが徹底されていると、「どこを変更していいか」「どこは触ってはいけないか」が直感的に分かるようになります。
つまり、アンダーバーはチーム開発の安全装置でもあるのです。
まとめ|アンダーバーは「意図を伝えるための記号」¶
ここまで、Pythonにおけるアンダーバーの意味と使い方を詳しく見てきました。 最後にポイントを整理しておきましょう。
アンダーバーの形 | 意味・用途 | ポイント |
---|---|---|
_ |
値を無視/REPLの結果 | 一時的・不要な値の扱いに便利 |
_var |
慣習的な非公開 | 「触らないで」を意味する |
__var |
名前マングリング | クラス内部専用 |
__var__ |
マジックメソッド | Pythonの内部動作を拡張 |
var_ |
予約語回避 | 命名の競合を防ぐ |
アンダーバーは見た目こそ地味ですが、コードの意図を伝えるための強力なサインです。 単なる記号ではなく、「この変数・関数はどう使うべきか」を読み手に伝えるための工夫なのです。
Pythonは「シンプルで読みやすいコード」を最も重視する言語です。 その哲学を体現するのが、このアンダーバーの文化です。
「使わない変数を_にする」「内部用の関数に_をつける」── たった1文字の違いが、コードの伝わり方を大きく変えます
これからPythonを書いていくときは、ぜひアンダーバーの意味を意識してみてください。 そうすれば、あなたのコードはより読みやすく、よりPythonic(Pythonらしい)ものになるはずです。
ここまでお読みいただきありがとうございました!