a = value는 값을 상자에 복사해 넣는 동작이 아니야. 이미 만들어진 객체를 a라는 이름이 가리키게 해. 그래서 b = a 뒤에는 두 이름이 같은 객체를 가리킬 수 있어.
같은 값과 같은 객체는 다르다
==는 값이 같은지 묻고, is는 바로 그 객체인지 물어. None처럼 하나뿐인 객체는 is None으로 비교하지만, 문자열이나 숫자의 값 비교에 is를 쓰면 안 돼. id()는 실행 중 객체의 정체성을 확인하는 데 도움이 돼.
가변 객체의 별명이 만드는 놀라움
리스트를 두 이름이 함께 가리킨 상태에서 한쪽을 바꾸면 다른 쪽에서도 바뀐 값이 보여. 별도의 바깥 컨테이너가 필요하면 얕은 복사를, 안쪽의 가변 객체까지 분리해야 하면 deepcopy를 검토해. 무엇을 공유하고 무엇을 복제할지 먼저 정하는 게 핵심이야.
언패킹과 증강 할당
a, b = b, a처럼 여러 값을 한 번에 풀어 받을 수 있어. +=는 정수처럼 불변인 객체에서는 새 값을 다시 묶지만, 리스트에서는 같은 객체를 제자리에서 바꿀 수 있어. 같은 문법이 객체의 가변성에 따라 다른 정체성 결과를 낳아.
미리 보는 함정: 함수 기본값에 리스트를 두면 호출 사이에도 같은 객체가 남아. 함수 수업에서 안전한 형태를 다시 배울 거야.
Code
이름은 객체를 가리킨다·python
>>> x = 42
>>> y = x # y 가 이제 x 와 *같은* 객체를 가리킴
>>> id(x) == id(y)
True
>>> x = 100 # x 가 새 객체로 다시 가리킴; y 는 여전히 42 가리킴
>>> y
42
>>> id(x) == id(y)
False
값의 같음과 객체의 같음·python
>>> a = [1, 2, 3]
>>> b = [1, 2, 3] # 같은 내용의 *다른* list
>>> a == b
True # 값이 같음
>>> a is b
False # 메모리상 다른 객체
>>> c = a # c 가 a 와 *같은* 객체를 가리킴
>>> a is c
True # 같은 객체
>>> # None 체크의 PEP 8 idiom:
>>> x = None
>>> if x is None: ... # 맞음
>>> if x == None: ... # 동작은 하지만 idiomatic 아님
같은 가변 객체를 가리킬 때 생기는 일·python
>>> a = [1, 2, 3]
>>> b = a # b 가 copy 받는 게 아님 — *같은* list 받음
>>> b.append(4) # b 통해 변경
>>> a # a 도 보임 — 처음부터 list 는 하나뿐
[1, 2, 3, 4]
>>> # 진짜 copy:
>>> b = a.copy() # shallow copy — 새 list, 같은 element
>>> # 또는 b = list(a) 또는 b = a[:]
>>> # 중첩 구조 (list of lists) 면 deep copy 필요:
>>> import copy
>>> b = copy.deepcopy(a)
튜플 언패킹으로 값 바꾸기·python
>>> # Pythonic swap — 임시 변수가 필요 없어.
>>> a, b = 1, 2
>>> a, b = b, a
>>> a, b
(2, 1)
>>> # 함수에서 언패킹:
>>> def get_pair():
... return "hello", 42
>>> name, count = get_pair()
>>> # Star 언패킹 — 나머지가 list 로:
>>> first, *middle, last = [1, 2, 3, 4, 5]
>>> first, middle, last
(1, [2, 3, 4], 5)
정수와 리스트에서 +=가 다른 이유·python
>>> # Immutable: x += 1 은 새 int 생성.
>>> x = 10
>>> id(x)
4327683600
>>> x += 1
>>> id(x)
4327683632 # 다른 객체
>>> # Mutable: list += other 는 in-place 변경.
>>> a = [1, 2, 3]
>>> id(a)
4385720128
>>> a += [4, 5]
>>> id(a)
4385720128 # 같은 객체 — a 가 in-place 변경됨
>>> # 비교: a = a + [4, 5] 는 새 list 만들고 a 를 다시 가리키게 했을 거야.
>>> # 비슷해 보여, 미묘하게 달라.
가변 기본값 함정 미리 보기·python
# 이렇게 하지 마:
def add_item(item, items=[]):
items.append(item)
return items
print(add_item('a')) # ['a']
print(add_item('b')) # ['a', 'b'] — 깜짝!
print(add_item('c')) # ['a', 'b', 'c'] — 셋이 한 list 공유
# 이렇게 해:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item('a')) # ['a']
print(add_item('b')) # ['b'] — 호출마다 fresh list
REPL에서 a = [1, 2, 3], b = a를 만든 뒤 b.append(4)가 a에 어떤 영향을 줄지 먼저 예상하고 확인해. 이번에는 b = a.copy()로 다시 해보고, 두 경우의 id(a)와 id(b)를 비교해. 왜 결과가 달라졌는지 객체와 이름의 관계로 설명해봐.
Progress
Progress is local-only — sign in to sync across devices.
Exercise 했어. quest내용 다 소화를 못하겠네. 우선 좀 진도 나가고 다시 돌아와서 또 봐야할거 같아.
"b = a는 하나의 객체에 이름표를 하나 더 붙인 것이고, b = a.copy()는 아예 새로운 객체를 만들어 독립시켰기 때문에 결과가 다름"