copy()는 칸 값이 같은 새 리스트를 만들어 돌려주는 리스트 메서드입니다. b = a는 같은 리스트에 이름을 하나 더 붙일 뿐이지만, b = a.copy()로 만든 사본은 원래 리스트와 따로 바뀝니다.
주문을 고치기 전에 처음 주문을 남겨 두고 싶을 때가 있습니다. before = orders처럼 이름을 하나 더 붙이면 남은 것 같지만, 리스트는 하나뿐이라 고친 것이 before로도 보입니다(리스트와 이름 둘). 따로 남기려면 리스트를 하나 더 만들어야 합니다.
1이름을 더 붙이기와 사본 만들기
그림의 코드입니다.
orders = ['커피', '라테']
today = orders
backup = orders.copy()
orders.append('쿠키')
print(today)
print(backup)
['커피', '라테', '쿠키']
['커피', '라테']2번 줄 today = orders는 새 리스트 없이 today를 orders와 같은 리스트 ①에 붙입니다. 3번 줄 orders.copy()는 칸 값이 같은 새 리스트 ②를 만들어 돌려주고, backup은 ②에 붙습니다. 이렇게 같은 값을 하나 더 새로 만든 것을 사본(copy)이라고 합니다.
4번 줄은 ①에 '쿠키'를 더합니다. ①을 가리키는 today로 찍으면 '쿠키'가 보이고, ②를 가리키는 backup으로 찍으면 보이지 않습니다(규칙 3).
copy()는 리스트를 제자리에서 바꾸기의 메서드들과 달리 리스트를 바꾸지 않고 새 리스트를 돌려줍니다. 그래서 backup = orders.copy()처럼 돌려받은 리스트에 이름을 붙입니다.
2고치기 전 리스트 남기기
주문의 0번 칸을 고치기 전에, 처음 주문을 before로 남겨 두려 합니다. 무엇이 찍힐까요?
orders = ['커피', '라테']
before = orders
orders[0] = '녹차'
print(before)
실행 결과 보기
['녹차', '라테']예상과 다르면 그곳이 배울 곳입니다. 2번 줄은 사본을 만들지 않고 같은 리스트에 이름 before를 하나 더 붙였습니다. 3번 줄이 그 리스트의 0번 칸을 바꾸니 before로 봐도 바뀌어 있습니다(규칙 3).
처음 주문을 남기려면 2번 줄을 before = orders.copy()로 씁니다.
orders = ['커피', '라테']
before = orders.copy()
orders[0] = '녹차'
print(before)
print(orders)['커피', '라테']
['녹차', '라테']3같은 리스트인가, 칸 값이 같은가
orders = ['커피', '라테']
today = orders
backup = orders.copy()
print(today is orders)
print(backup is orders)
print(backup == orders)
True
False
Trueis는 두 이름이 같은 리스트를 가리키는지, 곧 그림의 꼬리표가 같은지 묻습니다. == 연산자는 칸 값이 같은지 묻습니다. backup은 칸 값은 같지만 다른 리스트라서 is로는 False, == 연산자로는 True입니다.
예제
사본으로 내일 주문 만들기
오늘 주문의 사본으로 내일 주문을 만들고, 사본만 고칩니다.
orders = ['커피', '라테']
tomorrow = orders.copy()
tomorrow.remove('라테')
tomorrow.append('녹차')
print(orders)
print(tomorrow)
['커피', '라테']
['커피', '녹차']3·4번 줄의 remove()·append()는 tomorrow가 가리키는 사본을 제자리에서 바꿉니다. orders의 리스트는 건드리지 않아 오늘 주문이 그대로 남습니다.
자주 틀리는 곳
틀린 생각: 리스트를 따로 두려면 b = a로 충분하다.
이름 b가 따로 생기니 리스트도 둘이 된 것처럼 보이지만, 이름만 둘이고 리스트는 하나입니다.
a = [1, 2]
b = a
c = a.copy()
a.append(3)
print(b)
print(c)
[1, 2, 3]
[1, 2]a로 더한 3이 b로는 보이고, 사본 c에는 보이지 않습니다.
맞는 규칙: b = a는 같은 리스트에 이름을 하나 더 붙일 뿐입니다. 따로 바꿀 리스트가 필요하면 b = a.copy()로 새 리스트를 만듭니다(규칙 3).
틀린 생각: copy()도 리스트 메서드라서 None을 돌려준다.
append()·remove()가 None을 돌려주니 copy()도 그럴 것 같습니다. copy()는 리스트를 바꾸지 않는 대신 새 리스트를 돌려줍니다.
a = [1, 2]
b = a.copy()
print(b)
[1, 2]맞는 규칙: append()·extend()·remove()는 리스트를 바꾸고 None을 돌려주지만, 바꾸지 않는 copy()는 새 리스트를 돌려줍니다. 그래서 b = a.copy()처럼 돌려받은 리스트에 이름을 붙입니다.
틀린 생각: 칸 값이 같은 리스트 둘은 같은 리스트다.
찍으면 똑같이 보이지만, 대괄호로 쓸 때마다 리스트가 새로 만들어집니다.
a = [1, 2]
b = [1, 2]
print(a == b)
print(a is b)
True
False맞는 규칙: 대괄호로 쓸 때마다 새 리스트가 만들어집니다. 칸 값이 같은지는 == 연산자로, 한 리스트를 가리키는지는 is로 묻습니다(규칙 3).
확인 문제
1. 1절 코드의 4번 줄을 backup.append('쿠키')로 바꿨습니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
orders = ['커피', '라테']
today = orders
backup = orders.copy()
backup.append('쿠키')
print(today)
print(backup)
힌트
3번 줄 뒤 이름 셋이 각각 어느 리스트를 가리키는지 이름표로 그려 봅니다.
정답
['커피', '라테']
['커피', '라테', '쿠키']4번 줄은 backup이 가리키는 사본 ②에만 '쿠키'를 더합니다. today는 orders와 같은 ①을 가리키므로 칸 둘 그대로입니다.
흔한 오답은 첫 줄도 ['커피', '라테', '쿠키']로 쓰는 것입니다. copy()도 같은 리스트에 이름만 하나 더 붙인다고 본 것입니다. copy()는 새 리스트를 만듭니다(규칙 3).
2. orders는 그대로 두고 today에만 '쿠키'를 더하려 합니다. 실행 결과가 아래 두 줄이 되도록 빈칸을 채우세요.
['커피', '라테']
['커피', '라테', '쿠키']
orders = ['커피', '라테']
today = ________
today.append('쿠키')
print(orders)
print(today)
힌트
3번 줄 뒤에 orders와 today가 각각 어떤 리스트를 가리켜야 하는지 이름표로 그려 봅니다.
정답
orders.copy()입니다.
orders = ['커피', '라테']
today = orders.copy()
today.append('쿠키')
print(orders)
print(today)['커피', '라테']
['커피', '라테', '쿠키']다르게 써도 되는 곳: orders[:]도 같은 결과입니다. 처음부터 끝까지 자른, 칸 값이 같은 새 리스트입니다. 빈칸에 ['커피', '라테']를 그대로 써도 같은 두 줄이 찍히지만, 1번 줄의 주문을 바꾸면 today는 따라 바뀌지 않습니다.
흔한 오답은 orders입니다. 그러면 두 줄 모두 ['커피', '라테', '쿠키']가 찍힙니다. b = a를 사본으로 본 것입니다(복사된다는 생각).
3. 어제 걸음 수를 고치기 전에 처음 기록을 saved에 남기려 했습니다. 그런데 처음 기록 [5000, 7000]이 아니라 [6000, 7000]이 찍힙니다. 몇 번 줄을 어떻게 고쳐야 할까요?
steps = [5000, 7000]
saved = steps
steps[0] = 6000
print(saved)
[6000, 7000]힌트
4번 줄에서 saved와 steps가 가리키는 리스트가 몇 개인지 이름표로 그려 봅니다.
정답
2번 줄을 saved = steps.copy()로 고칩니다.
steps = [5000, 7000]
saved = steps.copy()
steps[0] = 6000
print(saved)[5000, 7000]고치기 전 2번 줄은 saved를 steps와 같은 리스트에 붙였을 뿐이라, 3번 줄이 바꾼 0번 칸이 saved로도 보였습니다. 2번 줄이 그때의 기록을 따로 담는다고 본 것입니다(복사된다는 생각).
다르게 고쳐도 되는 곳: 2번 줄을 saved = steps[:]로 써도 [5000, 7000]이 찍힙니다. steps[:]는 처음부터 끝까지 자른 새 리스트입니다. 3번 줄을 steps = [6000, 7000]처럼 새 리스트에 다시 붙여도 saved는 처음 리스트에 남지만, 칸 하나를 고칠 때마다 리스트를 통째로 다시 써야 합니다.
아래 코드 4번 줄 다음에 backup.append('녹차')를 한 줄 더하면 두 print가 무엇을 찍는지 봅니다.
처음 펼 때 약 6MB를 받습니다.컴퓨터에서 해 보기
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.