정렬(sort)은 값을 정한 차례대로 다시 놓는 일입니다. 따로 정하지 않으면 작은 것부터 놓습니다. sorted()는 정렬한 새 리스트를 돌려주고, .sort()는 같은 리스트를 제자리에서 정렬한 뒤 None을 돌려줍니다.
주문 목록을 가나다 차례로 보려면 둘 가운데 하나를 씁니다. 둘을 헷갈리면 처음 차례를 잃거나, 정렬된 리스트 대신 None에 이름을 붙이게 됩니다.
1sorted는 정렬한 새 리스트를 돌려준다
그림의 앞 두 줄 뒤에 print를 둘 붙였습니다.
orders = ['라테', '커피', '녹차']
ranked = sorted(orders)
print(ranked)
print(orders)
['녹차', '라테', '커피']
['라테', '커피', '녹차']2번 줄의 sorted(orders)는 orders가 가리키는 리스트 ①의 값을 작은 것부터 놓은 새 리스트 ②를 만들어 돌려줍니다. 이름 ranked는 그 ②에 붙습니다(규칙 2).
sorted는 ①을 건드리지 않아서 4번 줄은 처음 차례 그대로 찍습니다. 원래 값은 두고 새 값을 만든다는 점이 문자열 메서드의 upper()와 같습니다.
작은 것부터 놓는 이 차례를 오름차순이라고 합니다. 문자열은 참과 거짓, 비교에서 본 글자 차례(한글은 가나다, 영어는 대문자가 소문자보다 앞)로 놓습니다. 큰 것부터 놓는 내림차순은 reverse=True를 함께 넘깁니다(sorted(orders, reverse=True)).
2sort는 같은 리스트를 제자리에서 바꾼다
이번에는 그림의 4번 줄처럼 .sort()를 씁니다.
orders = ['라테', '커피', '녹차']
result = orders.sort()
print(orders)
print(result)
['녹차', '라테', '커피']
None.sort()는 orders가 가리키는 ① 자체를 제자리에서 정렬합니다. 새 리스트는 생기지 않고 orders는 그대로 ①을 가리키므로, 3번 줄이 정렬된 차례를 찍습니다.
sort가 돌려주는 값은 돌려줄 값이 없다는 뜻의 None이고, 2번 줄은 그 None에 이름 result를 붙입니다(규칙 2). 리스트를 제자리에서 바꾸기의 append()가 None을 돌려주는 것과 같습니다.
orders와 같은 리스트에 이름 backup을 하나 더 붙여 두고 정렬합니다. 4번 줄은 무엇을 찍을까요?
orders = ['커피', '라테', '녹차']
backup = orders
orders.sort()
print(backup)
실행 결과 보기
['녹차', '라테', '커피']예상과 다르면 그곳이 배울 곳입니다.
2번 줄 backup = orders는 사본을 만들지 않고, orders가 가리키는 바로 그 리스트에 이름 backup을 하나 더 붙입니다. 3번 줄이 그 리스트를 제자리에서 정렬하니 backup으로 봐도 정렬되어 있습니다(규칙 3).
처음 차례를 따로 남기려면 정렬하기 전에 backup = orders.copy()로 사본을 만듭니다(리스트 복사: copy와 이름 더 붙이기).
예제
주문을 가나다 차례로 찍기
orders = ['커피', '라테', '커피']
for item in sorted(orders):
print(item)
라테
커피
커피2번 줄은 sorted가 돌려준 새 리스트를 이름 없이 바로 for에 넘깁니다. 같은 값 '커피' 둘은 나란히 놓이고, orders는 처음 차례 그대로입니다.
sort가 돌려준 값에서 꺼내면
가장 싼 가격을 꺼내려고, sort의 결과에 이름 prices를 다시 붙였습니다.
prices = [4500, 3500, 4000]
prices = prices.sort()
print(prices[0])
Traceback (most recent call last): File "main.py", line 3, in <module> print(prices[0]) ~~~~~~^^^TypeError: 'NoneType' object is not subscriptable맨 아래 줄부터 읽습니다. NoneType(None의 종류)은 대괄호로 칸을 꺼낼 수 없다(not subscriptable)는 뜻입니다. 3번 줄에서 prices가 None을 가리켰다는 말입니다.
까닭은 2번 줄입니다. sort가 돌려준 None에 prices를 다시 붙여, 정렬된 리스트는 가리키는 이름이 없어졌습니다.
오류는 3번 줄에서 났지만 고칠 곳은 2번 줄입니다. prices.sort()만 쓰면 3번 줄이 3500을 찍습니다.
자주 틀리는 곳
틀린 생각: 다른 이름을 붙여 둔 리스트는 한쪽에서 정렬해도 다른 이름 쪽은 처음 차례로 남는다.
이름이 둘이면 리스트도 둘인 것처럼 보이고, backup이라는 이름도 사본처럼 읽힙니다. 그러나 backup = orders는 리스트를 하나 더 만들지 않습니다.
orders = ['커피', '라테', '녹차']
backup = orders
orders.sort()
print(backup)
['녹차', '라테', '커피']리스트는 하나이고 이름이 둘이라, 제자리에서 정렬된 차례가 backup으로도 보입니다.
맞는 규칙: sort는 새 리스트를 만들지 않고 가리키는 리스트를 제자리에서 바꾸므로, 그 리스트에 붙은 모든 이름에서 바뀐 차례가 보입니다. 처음 차례를 남기려면 정렬하기 전에 copy()로 사본을 만듭니다(규칙 3).
틀린 생각: 문자열을 sorted로 정렬하면 글자를 정렬한 문자열이 나온다.
sorted는 정렬한 새 값을 돌려주니 문자열을 넘기면 문자열이 돌아올 것 같습니다. 돌려주는 것은 늘 리스트입니다.
word = 'cab'
print(sorted(word))
['a', 'b', 'c']sorted는 받은 값에서 하나씩 꺼내 새 리스트를 만듭니다. 문자열에서는 break와 continue의 for ch in '커라커쿠':처럼 글자가 하나씩 나옵니다.
맞는 규칙: sorted는 무엇을 받든 값을 하나씩 꺼내 정렬한 새 리스트를 돌려줍니다. 문자열을 넘기면 글자 하나짜리 문자열의 리스트가 나옵니다.
확인 문제
1. 1절 코드의 리스트를 바꿨습니다. 무엇이 찍히는지 두 줄을 글자 그대로 쓰세요.
orders = ['쿠키', '커피', '녹차']
ranked = sorted(orders)
print(ranked)
print(orders)
힌트
2번 줄 뒤에 orders와 ranked가 각각 어느 리스트를 가리키는지 그려 봅니다. '커'와 '쿠'는 첫소리가 같으니 모음끼리 견줍니다.
정답
['녹차', '커피', '쿠키']
['쿠키', '커피', '녹차']sorted는 정렬한 새 리스트를 돌려주고 ranked가 그 리스트에 붙습니다. orders가 가리키는 리스트는 처음 차례 그대로입니다. 가나다 차례에서 '커'의 ㅓ가 '쿠'의 ㅜ보다 앞입니다.
흔한 오답은 둘째 줄도 ['녹차', '커피', '쿠키']로 쓰는 것입니다. sorted도 처음 리스트를 바꾼다고 본 것입니다. 제자리에서 바꾸는 것은 sort입니다(규칙 3).
2. 처음 차례는 그대로 두고, 작은 것부터 놓은 새 리스트를 찍으려 합니다. 다 채운 코드는 아래 두 줄을 찍어야 합니다.
[2000, 3500, 4000]
[4000, 2000, 3500]
2번 줄의 빈칸을 채우세요.
prices = [4000, 2000, 3500]
low = ________
print(low)
print(prices)
힌트
나와야 할 둘째 줄을 봅니다. 2번 줄이 끝난 뒤에도 prices가 가리키는 리스트는 어떤 차례여야 할까요?
정답
sorted(prices)입니다.
prices = [4000, 2000, 3500]
low = sorted(prices)
print(low)
print(prices)[2000, 3500, 4000]
[4000, 2000, 3500]sorted가 정렬한 새 리스트를 돌려주고 low가 그 리스트에 붙습니다. prices가 가리키는 리스트는 건드리지 않습니다.
다르게 써도 되는 곳: sorted(prices, reverse=False)도 같습니다. 빈칸에 [2000, 3500, 4000]을 바로 써도 같은 두 줄이 찍히지만, 1번 줄의 가격을 바꾸면 low가 따라 바뀌지 않습니다.
흔한 오답은 prices.sort()입니다. 그러면 low는 sort가 돌려준 None에 붙고 prices가 제자리에서 정렬되어, None과 [2000, 3500, 4000]이 찍힙니다. sort도 sorted처럼 정렬한 새 리스트를 돌려준다고 본 것입니다.
3. 사흘 동안 걸은 걸음 수에 이름 week를 하나 더 붙여 두고 정렬했습니다. 무엇이 찍힐까요?
steps = [8200, 6100, 9400]
week = steps
week.sort()
print(steps)
힌트
2번 줄 뒤에 steps와 week가 각각 어느 리스트를 가리키는지 그려 봅니다.
정답
[6100, 8200, 9400]2번 줄은 steps가 가리키는 리스트에 이름 week를 하나 더 붙입니다. 3번 줄이 그 하나뿐인 리스트를 제자리에서 정렬하므로, steps로 찍어도 정렬된 차례입니다.
흔한 오답은 [8200, 6100, 9400]입니다. week가 사본을 따로 받았다고 본 것입니다(복사된다는 생각). week = steps는 같은 리스트에 이름을 하나 더 붙일 뿐입니다(규칙 3).
아래 코드 3번 줄을 orders = sorted(orders)로 바꾸면 4번 줄이 무엇을 찍는지 봅니다.
처음 펼 때 약 6MB를 받습니다.컴퓨터에서 해 보기
파이썬 3.14. Tab을 누르면 다음 단추나 칸으로 갑니다. 들여쓰기는 빈칸 네 개입니다. Enter는 앞줄 들여쓰기를 잇고, 콜론 뒤에서는 한 단계 더 들여 씁니다. Ctrl+Enter로 실행합니다.
'실행'을 누르면 여기에 나옵니다.
여기서 쓴 코드 · 내 예상은 저장하지도 운영자에게 보내지도 않습니다. 페이지를 새로 열면 처음 코드입니다.