분실 신고서
LOST-001
신고인
여행사 직원 박 대리
잃어버린 것
단체 기념품 목록. 예비용으로 '복사'해 둔 목록에 자석을 추가했더니, 원래 목록에도 자석이 들어가 있었다.
해결 조건
두 목록이 처음부터 같은 가방이었음을 코드로 증명하고, 진짜 예비 목록을 만든다.
하늘섬 국제공항 수하물 센터
입사 첫날 아침, 도미란 반장이 컨베이어 앞에서 태그 뭉치를 건넵니다. "이 센터에서 제일 먼저 외울 말이 있어. 가방은 하나, 태그는 여럿."
첫 신고는 여행사 직원입니다. 기념품 목록을 예비용으로 하나 더 만들었는데, 예비 목록에 적은 것이 원래 목록에도 나타난다고 합니다. 반장이 코드를 보고 웃습니다. "목록이 두 개라고? 태그가 두 개겠지."
= (9분)신고인의 코드는 이렇습니다.
souvenirs = ["postcard", "keyring"]
backup = souvenirs
backup.append("magnet")
print(souvenirs)
# ['postcard', 'keyring', 'magnet']backup = souvenirs는 리스트를 복사하지 않습니다. souvenirs라는 태그가 매달린 그 가방에 backup이라는 태그를 하나 더 매답니다. 가방은 처음부터 하나였고, backup.append는 그 하나뿐인 가방에 자석을 넣었습니다.
= 의 오른쪽을 먼저 계산해 객체(가방)를 얻고, 왼쪽 이름(태그)을 그 객체에 묶습니다.아래 태그 보드에서 한 줄씩 진행해 보세요. 왼쪽 칸은 이름표, 오른쪽은 가방입니다. 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에 머그잔을 넣어도 원래 목록은 그대로입니다. (이 복사가 "한 층만" 새로 만든다는 점은 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
눌러 보며 배우는 파이썬과 Reflex. 모든 예제는 Reflex 0.10.0에서 직접 실행해 확인했습니다.
ReflexKR은 배너 광고 없이 무료로 운영돼요. 도움이 되셨다면 커피 한 잔으로 응원해 주세요.
© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
질문과 답변
이 교시에서 궁금한 점을 남겨 주세요. 모든 언어 페이지의 질문이 함께 모입니다.