紛失届
LOST-001
届出人
旅行会社の社員、パクさん
なくしたもの
団体のおみやげリスト。予備として「コピー」しておいたリストにマグネットを足したら、元のリストにもマグネットが入っていた。
解決の条件
二つのリストが最初から同じかばんだったことをコードで証明し、本物の予備リストを作る。
ハヌルソム国際空港 手荷物センター
入社初日の朝、ド・ミラン班長がコンベヤーの前でタグの束を手渡します。「このセンターでまず覚える言葉がある。かばんは一つ、タグはいくつも」
最初の届出人は旅行会社の社員です。おみやげリストを予備用にもう一つ作ったのに、予備のリストに書いたものが元のリストにも現れるといいます。班長はコードを見て笑います。「リストが二つ? タグが二つ、の間違いでしょう」
= (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
実習台を準備中…
いま変わったもの
封印されたかばん(イミュータブル)
すべてのオブジェクトは三つの性質を持っています。
| 調べ方 | 空港でいえば | |
|---|---|---|
| 同一性(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 Truex と 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 のように、世界に一つしかないオブジェクトを確かめるときだけ使います。
オブジェクトは数値やリストだけではありません。関数も、クラスも、モジュールも、名前に結び付けられたオブジェクトです。
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())
# hidef greet(): は関数オブジェクトを作り、greet という名前を結び付ける、一種の代入です。del greet で名前を外しても、alias が同じ関数オブジェクトを指しているので、関数はそのまま残ります。type(int) も type(type) も <class 'type'> です。この話は7限目でもう一度します。名前に対してできることは、二つしかありません。
a = ...。名前を別のオブジェクトに結び付け直します。元のかばんはそのままです。a.append(...)、a[0] = ...。名前はそのままで、かばんの中身が変わります。同じかばんを指すすべての名前から見えます。a = [1, 2]
b = a
a = a + [3]
print(a, b, a is b)
# [1, 2, 3] [1, 2] Falsea = [1, 2]
b = a
a.append(3)
print(a, b, a is b)
# [1, 2, 3] [1, 2, 3] Truea + [3] は新しいリストを作り、a = がタグ a をその新しいリストに付け替えます。b は元のかばんに残ります。一方 append はかばんそのものを変えるので、b からも見えます。下で二つのやり方を交互に動かしてみてください。
タグボード
ステップ 1 / 0
次に実行する行: 0
実習台を準備中…
いま変わったもの
封印されたかばん(イミュータブル)
1、2 は小さな値なので、矢印の代わりに値で書きました。実はこれらもオブジェクトで、リストはそのオブジェクトを指す参照を入れています(3限目)。a += [3] はどちらでしょう? リストではかばんの変更です。ところが数値や文字列では、タグの付け替えになります。この二つの顔が2限目のテーマです。del はかばんではなくタグを外す (6分)c = ["tag"]
d = c
del c
print(d)
# ['tag']
print(c)
# NameError: name 'c' is not defineddel c は名前 c をなくすだけで、リストを消しはしません。d がまだ指しているので、かばんは残ります。かばんが本当に消えるのは、どのタグもそのかばんを指さなくなったときです(11限目)。
二つの名前を入れ替える p, q = q, p も、タグの付け替えです。右辺の q, p で先にタプルを作り、その中のオブジェクトに左辺の名前を順番に結び付けます。
p, q = "left", "right"
p, q = q, p
print(p, q)
# right left届出人の二つのリストが同じかばんだった証拠と、本物の予備リストを作る方法です。
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'] Falselist(souvenirs) は新しいリストを作ります。これで safe にマグカップを入れても、元のリストはそのままです。(このコピーが「1層だけ」新しく作るという点は3限目で扱います。)
退勤まぎわ、ピンが13番コンベヤーのほうを指します。タグが一枚もないかばんが二つ、ずっと回り続けているという報告です。班長は「タグがないなら、とっくに片付けられているはずなのに」とだけ言って、画面を消します。
解決報告 — LOST-001。リストは最初から一つで、タグが二枚あっただけ。is と id で確認し、list() で新しいリストを作って解決。
x = [0]、y = x、x = [1] を順に実行すると、y は何になるでしょう? 先に図を描いてから、実行して確かめてください。a = [1, 2] のとき、b = a[:] と c = a を作り、a is b、a is c、a == b の結果を予想してみてください。print に別の名前を付けてから del print をすると、どうなるでしょう? 組み込みの名前がどこにあるかは5限目で学びます。班長の業務手帳
変数は箱ではなく名札。= は右辺のオブジェクトに左辺の名前を結び付ける。
オブジェクトの三つの性質:同一性(id, is)、型(type)、値(==)。
is は同じオブジェクトか、== は値が同じか。値の比較はいつでも ==。
関数・クラス・モジュールもオブジェクト。def も名前を結び付ける代入だ。
再束縛(a = …)は名前を移し、変更(a.append …)はオブジェクトを変える。
del は名前を外すだけ。オブジェクトは誰からも指されなくなったときに消える。
新しい授業・講座のお知らせを受け取る
この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。
R
ReflexKR
触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。
ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する
アフィリエイトと支援について© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
質問と回答
この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。