R

ReflexKR

Reflex公式ドキュメント
名札の空港:Pythonのオブジェクトモデル
1限目

時間 0:00–0:50

タグはかばんではない:名前とオブジェクト

紛失届

LOST-001

かばんは二つだと思っていた

届出人

旅行会社の社員、パクさん

なくしたもの

団体のおみやげリスト。予備として「コピー」しておいたリストにマグネットを足したら、元のリストにもマグネットが入っていた。

解決の条件

二つのリストが最初から同じかばんだったことをコードで証明し、本物の予備リストを作る。

ハヌルソム国際空港 手荷物センター

入社初日の朝、ド・ミラン班長がコンベヤーの前でタグの束を手渡します。「このセンターでまず覚える言葉がある。かばんは一つ、タグはいくつも」

最初の届出人は旅行会社の社員です。おみやげリストを予備用にもう一つ作ったのに、予備のリストに書いたものが元のリストにも現れるといいます。班長はコードを見て笑います。「リストが二つ? タグが二つ、の間違いでしょう」

1-1. タグを付ける = (9分)

届出人のコードはこうです。

souvenirs = ["postcard", "keyring"]
backup = souvenirs
backup.append("magnet")
print(souvenirs)
# ['postcard', 'keyring', 'magnet']

backup = souvenirs はリストをコピーしません。souvenirs というタグがぶら下がっているそのかばんに、backup というタグをもう一枚ぶら下げるだけです。かばんは最初から一つで、backup.append はその一つしかないかばんにマグネットを入れました。

  • = はまず右辺を計算してオブジェクト(かばん)を得て、左辺の名前(タグ)をそのオブジェクトに結び付けます。
  • 右辺がすでにある名前なら、新しいオブジェクトは生まれません。同じオブジェクトに名前が一つ増えるだけです。

下のタグボードで1行ずつ進めてみてください。左の欄が名札、右がかばんです。3行目の手前では、結果を先に予想しないと先へ進めません。

タグボード

ステップ 1 / 0

次に実行する行: 0

実習台を準備中…

いま変わったもの

封印されたかばん(イミュータブル)

2行目を過ぎても、かばんは一つだけです。2本の矢印が同じリストを指しているか見てください。

1-2. かばんの三つの性質:同一性、型、値 (8分)

すべてのオブジェクトは三つの性質を持っています。

調べ方空港でいえば
同一性(identity)id(obj)、a is bかばんの底に刻まれた固有番号
型(type)type(obj)かばんの種類(スーツケース、リュック…)
値(value)== で比較中に入っている中身
x = ["postcard"]
y = ["postcard"]
print(x == y, x is y)
# True False
print(id(x) == id(y), id(souvenirs) == id(backup))
# False True
  • x と y は、中身がまったく同じ別々のかばんです。== は True、is は False。
  • souvenirs と backup は同じかばんなので、id も同じです。
  • id の数字そのものに意味はありません。CPythonではメモリアドレスですが、実行するたびに変わります。比較にだけ使ってください。
print(type(x), type(len))
# <class 'list'> <class 'builtin_function_or_method'>

ピンの案内

→ is は「同じかばんか」、== は「中身が同じか」です。値が同じかを見るときは、いつでも == を使いましょう。is は x is None のように、世界に一つしかないオブジェクトを確かめるときだけ使います。

1-3. すべてはかばんである (6分)

オブジェクトは数値やリストだけではありません。関数も、クラスも、モジュールも、名前に結び付けられたオブジェクトです。

shout = print
shout("boarding")
# boarding
print(shout is print)
# True

def greet():
    return "hi"

print(type(greet), greet.__name__)
# <class 'function'> greet
alias = greet
del greet
print(alias())
# hi
  • def greet(): は関数オブジェクトを作り、greet という名前を結び付ける、一種の代入です。
  • del greet で名前を外しても、alias が同じ関数オブジェクトを指しているので、関数はそのまま残ります。
  • クラスもオブジェクトです。type(int) も type(type) も <class 'type'> です。この話は7限目でもう一度します。

1-4. タグを付け替える、かばんを変える (11分)

名前に対してできることは、二つしかありません。

  1. タグの付け替え(再束縛):a = ...。名前を別のオブジェクトに結び付け直します。元のかばんはそのままです。
  2. かばんの変更(ミューテーション):a.append(...)、a[0] = ...。名前はそのままで、かばんの中身が変わります。同じかばんを指すすべての名前から見えます。
a = [1, 2]
b = a
a = a + [3]
print(a, b, a is b)
# [1, 2, 3] [1, 2] False
a = [1, 2]
b = a
a.append(3)
print(a, b, a is b)
# [1, 2, 3] [1, 2, 3] True

a + [3] は新しいリストを作り、a = がタグ a をその新しいリストに付け替えます。b は元のかばんに残ります。一方 append はかばんそのものを変えるので、b からも見えます。下で二つのやり方を交互に動かしてみてください。

タグボード

ステップ 1 / 0

次に実行する行: 0

実習台を準備中…

いま変わったもの

封印されたかばん(イミュータブル)

a = a + [3] では3行目のあと矢印 a が新しいかばんへ移り、a.append(3) では矢印はそのままで、かばんの中だけが変わります。
  • リストの図では、枠の中の 1、2 は小さな値なので、矢印の代わりに値で書きました。実はこれらもオブジェクトで、リストはそのオブジェクトを指す参照を入れています(3限目)。
  • a += [3] はどちらでしょう? リストではかばんの変更です。ところが数値や文字列では、タグの付け替えになります。この二つの顔が2限目のテーマです。

1-5. del はかばんではなくタグを外す (6分)

c = ["tag"]
d = c
del c
print(d)
# ['tag']
print(c)
# NameError: name 'c' is not defined

del c は名前 c をなくすだけで、リストを消しはしません。d がまだ指しているので、かばんは残ります。かばんが本当に消えるのは、どのタグもそのかばんを指さなくなったときです(11限目)。

二つの名前を入れ替える p, q = q, p も、タグの付け替えです。右辺の q, p で先にタプルを作り、その中のオブジェクトに左辺の名前を順番に結び付けます。

p, q = "left", "right"
p, q = q, p
print(p, q)
# right left

事件解決 (10分)

届出人の二つのリストが同じかばんだった証拠と、本物の予備リストを作る方法です。

souvenirs = ["postcard", "keyring"]
backup = souvenirs
backup.append("magnet")
print(souvenirs is backup, id(souvenirs) == id(backup))
# True True

safe = list(souvenirs)     # 新しいかばんを作り、同じ中身を入れる
safe.append("mug")
print(souvenirs, safe, safe is souvenirs)
# ['postcard', 'keyring', 'magnet'] ['postcard', 'keyring', 'magnet', 'mug'] False

list(souvenirs) は新しいリストを作ります。これで safe にマグカップを入れても、元のリストはそのままです。(このコピーが「1層だけ」新しく作るという点は3限目で扱います。)

退勤まぎわ、ピンが13番コンベヤーのほうを指します。タグが一枚もないかばんが二つ、ずっと回り続けているという報告です。班長は「タグがないなら、とっくに片付けられているはずなのに」とだけ言って、画面を消します。

解決報告 — LOST-001。リストは最初から一つで、タグが二枚あっただけ。is と id で確認し、list() で新しいリストを作って解決。

練習問題

  1. x = [0]、y = x、x = [1] を順に実行すると、y は何になるでしょう? 先に図を描いてから、実行して確かめてください。
  2. a = [1, 2] のとき、b = a[:] と c = a を作り、a is b、a is c、a == b の結果を予想してみてください。
  3. print に別の名前を付けてから del print をすると、どうなるでしょう? 組み込みの名前がどこにあるかは5限目で学びます。

班長の業務手帳

  • 変数は箱ではなく名札。= は右辺のオブジェクトに左辺の名前を結び付ける。

  • オブジェクトの三つの性質:同一性(id, is)、型(type)、値(==)。

  • is は同じオブジェクトか、== は値が同じか。値の比較はいつでも ==。

  • 関数・クラス・モジュールもオブジェクト。def も名前を結び付ける代入だ。

  • 再束縛(a = …)は名前を移し、変更(a.append …)はオブジェクトを変える。

  • del は名前を外すだけ。オブジェクトは誰からも指されなくなったときに消える。

← 前へ

講座の概要

次へ →

2限目 · 封印されたかばん:ミュータブルとイミュータブル

新しい授業・講座のお知らせを受け取る

この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。

収集項目:メールアドレス・目的:この講座の新しい授業・公開のお知らせ・保有期間:解除のご依頼まで。他の目的には使わず、第三者にも提供しません。お知らせメールに返信いただければすぐに削除します。

質問と回答

この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。

リンクや書式なしで、そのままの文字で表示されます。

R

ReflexKR

触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。

ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する

アフィリエイトと支援について
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex