isの概要
| オブジェクトの同一性(実体の同一)判定 Python予約語 | ||
|
is 概要 わかりやすく説明 |
||
|
isの考え方をイメージで理解

isの基本的な使い方
あるリスト a を作り、それをそのまま別の変数 b に「参照(リモコン)をコピー」したとき、両者が全く同じ実体を指しているかを検証する例です。
# is を使ったオブジェクトの同一性判定
a = [1, 2, 3]
b = a # aの「実体」が置いてあるメモリの場所をそのままbに教える(参照渡し)
print(a is b) # 結果: True(全く同じ実体)
print(id(a) == id(b)) # 内部ではこれと同じメモリアドレスの一致を調べています
b = aの処理は、データを複製したのではなく、1つのデータに対して「aという名前」と「bという名前」の2本のアクセスルート(参照)を用意した状態になるため、isはTrueを返します。
isと==の違い
「見た目(中身のデータ)が同じ」であることと、「コンピュータにとって同じ個体である」ことの決定的な違いが判る、最も分かりやすい例です。
# is と == の明確な違い
a = [1, 2, 3]
b = [1, 2, 3] # 新しくメモリ上の別の場所に、同じ中身のリストを作成
print(a == b) # 結果: True (中身の「1, 2, 3」という値が同じなので合格)
print(a is b) # 結果: False(中身は同じだが、メモリ上の住所が違う別オブジェクトなので不合格)
- 他言語でいう「値渡し」と「参照渡し」の理解に直結する部分です。リストなどの変更可能なオブジェクト(ミュータブル)を新しく定義すると、必ず新しいメモリアドレスが割り当てられます。
isを使ったNoneの判定(実務での最頻出パターン)
Python実務において is が最も多く使われ、開発の現場で鉄則とされている「データが空、または存在しない状態(None)」を判定する書き方です。
# None の安全な判定
x = None
if x is None:
print("x は何もデータを持っていない『None』という状態です")
NoneはPythonシステム全体の中で絶対に1つしか作られないという強力なルールがあるため、== Noneではなくis Noneを使うことで、最速かつ他のオブジェクトの誤作動(__eq__のオーバーライドバグなど)に巻き込まれずに判定できます。
isの応用例(シングルトンオブジェクトの判定)
None と同様に、論理値である True と False もPythonのシステム内部に1個ずつしか存在しないため、is を使ってオブジェクトが同一であることを瞬時に見破ることができます。
# シングルトンオブジェクトの判定
x = True
y = True
print(x is y) # 結果: True(同じTrueオブジェクトの場所を指している)
isの使用上の注意点
- 数値や文字列の比較に is を使ってはいけない(バグの温床):初心者が最も陥りやすい罠が、数値や文字列の一致判定に
isを使ってしまうことです。Pythonはパフォーマンス向上のため、特定の小さな整数(-5から256まで)や短い文字列をメモリ内部で勝手に使い回す(キャッシュする)という裏の仕組みを持っています。このため、たまたまisでTrueになることがあっても、値が大きくなった瞬間に突然Falseに切り替わり、予測不能なバグを生み出す原因になります。値の比較は必ず==を徹底してください。# 【非常に危険な挙動の例】 num1 = 100 num2 = 100 print(num1 is num2) # 結果: True (100はPythonが内部キャッシュしているため同一とみなされる) num3 = 1000 num4 = 1000 print(num3 is num4) # 結果: False(1000はキャッシュ対象外のため、別の個体として生成されてしまう!) # ※値の比較には絶対に「is」ではなく「==」を使ってください! - ミュータブルなオブジェクト(リストや辞書)の破壊的変更の影響:
isがTrueである2つの変数は、実体が1つしかありません。そのため、片方の変数を書き換えると、もう片方の変数の内容も自動的に、同時に書き換わります。これはデータ構造を扱う上でバグを引き起こしやすいため、別々のデータとして扱いたい場合はcopy.deepcopy()などを使用して、メモリ上の実体ごと複製(ディープコピー)する必要があります。
isのよくある質問
- Q: `if x is not None:` という書き方をよく見かけますが、これは何ですか?
- A: 「変数の値が、None(空っぽ)ではないとき」を判定する、Pythonの非常に美しく洗練された標準的なイディオム(定型文)です。
if not x is None:と書くよりも、英文として(x is not None)自然に読めるため、可読性を重視するPythonの文化において最も推奨される記述スタイルとなっています。# 実務で毎日使う、Noneの回避チェック if user_input is not None: print("有効なデータが入っています") - Q: `==` の代わりに全部 `is` を使ったほうが、処理スピードが速いと聞きましたが本当ですか?
- A: 確かに処理速度の面だけで言えば、
isはメモリアドレスの数字の羅列を1回比較するだけなので、オブジェクトの中身を深くまで精査する==よりも圧倒的に高速です。 しかし、前述の通り数値や文字列に対してisを使うと、Pythonの内部キャッシュの影響で予期せぬ判定漏れや致命的な計算バグを引き起こします。速度のために安全性を犠牲にするのは実務のプログラミングでは言語道断です。「None、True、Falseへの判定だけが is の領土であり、それ以外のデータの比較はすべて == に任せる」と厳格にルールを切り分けてください。
まとめ
is は、データの価値そのものではなく、そのオブジェクトが配置されているメモリ空間の「物理的な実体の同一性」を厳格に見極めるための演算子です。
- 2つの変数が全く同じメモリアドレス(オブジェクト)を指しているときにのみ
Trueを返す。 - 中身の「値」が等しいかを調べる
==とは文法的な役割が180度異なるため、混同は禁物。 - 実務における主戦場は
is Noneやis not Noneであり、これらを使うことで最も安全で高速な条件分岐を保証できる。
Pythonのメモリ管理の仕組み(参照渡しや整数のキャッシュ仕様)を深く理解し、is と == を完全にコントロールできるようになることで、裏でデータが勝手に書き換わるような事故のない、スマートで信頼性の高いPythonコードを記述できるようになりましょう。