본문 바로가기
언어별 개념 정리/Python

Python sorted와 list.sort 차이: 반환값·원본 변경·key 사용·선택 기준

by char_lie 2026. 9. 21.
반응형

파이썬에서 리스트를 정렬할 때 가장 자주 만나는 두 가지가 sorted()와 list.sort()다. 결과만 보면 둘 다 오름차순으로 정렬하지만, 코드를 작성할 때는 반환값과 원본 변경 여부가 완전히 다르다.

먼저 결론부터 정리하면 다음과 같다.

구분sorted(iterable)list.sort()

반환값 정렬된 새 list None
원본 변경 변경하지 않음 리스트 자체를 변경
사용 대상 모든 iterable list만 가능
key, reverse 지원 지원
안정 정렬 보장 보장

원본을 보존하면서 정렬 결과가 필요하면 sorted(), 현재 리스트 자체를 정렬하면 list.sort()를 선택하면 된다.

sorted는 정렬된 새 리스트를 반환한다

sorted()는 입력받은 iterable의 요소를 정렬해 새로운 리스트로 반환한다. 기존 리스트는 그대로 남는다.

numbers = [3, 1, 4, 2]

result = sorted(numbers)

print(numbers)  # [3, 1, 4, 2]
print(result)   # [1, 2, 3, 4]

원본과 결과가 서로 다른 리스트인지도 확인할 수 있다.

print(numbers is result)  # False

sorted()의 장점은 리스트가 아닌 iterable에도 사용할 수 있다는 점이다. 튜플, 문자열, 집합, 제너레이터도 정렬할 수 있으며 반환 형식은 항상 리스트다.

print(sorted((3, 1, 2)))  # [1, 2, 3]
print(sorted("cab"))      # ['a', 'b', 'c']
print(sorted({3, 1, 2}))  # [1, 2, 3]

집합은 원래 순서를 보장하기 위한 자료형이 아니지만, sorted()의 결과는 정렬된 리스트이므로 순서대로 사용할 수 있다.

list.sort는 원본 리스트를 직접 바꾼다

list.sort()는 리스트 내부의 요소 순서를 직접 바꾼다. 별도의 정렬 결과를 반환하지 않으며 반환값은 None이다.

numbers = [3, 1, 4, 2]

result = numbers.sort()

print(numbers)  # [1, 2, 3, 4]
print(result)   # None

이 차이를 놓치면 다음과 같은 실수가 생긴다.

numbers = [3, 1, 4, 2]
numbers = numbers.sort()

print(numbers)  # None

numbers.sort()가 정렬된 리스트를 반환할 것이라고 생각해 변수에 다시 대입했지만, 실제 반환값은 None이다. 원본을 직접 정렬할 때는 대입하지 않고 한 줄로 호출한다.

numbers = [3, 1, 4, 2]
numbers.sort()

print(numbers)  # [1, 2, 3, 4]

key 사용법은 둘이 같다

두 방식 모두 key에 함수를 전달해 각 요소에서 정렬 기준값을 꺼낼 수 있다. key 함수는 요소 하나를 받아 비교에 사용할 값을 반환한다.

예를 들어 문자열 길이를 기준으로 정렬하려면 len을 사용한다.

words = ["banana", "kiwi", "apple", "fig"]

print(sorted(words, key=len))
# ['fig', 'kiwi', 'apple', 'banana']

원본 리스트를 직접 바꾸려면 같은 기준을 sort()에 전달한다.

words = ["banana", "kiwi", "apple", "fig"]
words.sort(key=len)

print(words)
# ['fig', 'kiwi', 'apple', 'banana']

딕셔너리 목록은 람다 함수로 필요한 값을 선택할 수 있다.

users = [
    {"name": "민준", "score": 82},
    {"name": "서연", "score": 95},
    {"name": "지우", "score": 88},
]

ranked = sorted(users, key=lambda user: user["score"], reverse=True)

print(ranked)
# [{'name': '서연', 'score': 95},
#  {'name': '지우', 'score': 88},
#  {'name': '민준', 'score': 82}]

key 함수는 정렬 중 비교가 일어날 때마다 반복 호출되는 방식이 아니다. 입력 요소마다 한 번씩 계산된 기준값이 정렬에 사용된다. 따라서 비교 함수처럼 두 요소를 받도록 작성하면 안 된다.

여러 기준은 튜플 key로 정리한다

key가 튜플을 반환하면 앞의 값부터 차례로 비교한다. 점수는 높은 순서, 이름은 가나다순으로 정렬하는 예시는 다음과 같다.

users = [
    {"name": "지우", "score": 90},
    {"name": "민준", "score": 85},
    {"name": "서연", "score": 90},
]

ranked = sorted(
    users,
    key=lambda user: (-user["score"], user["name"]),
)

for user in ranked:
    print(user["name"], user["score"])

실행 결과는 다음과 같다.

서연 90
지우 90
민준 85

숫자 점수에 음수를 적용해 내림차순 기준을 만들고, 점수가 같을 때만 이름을 오름차순으로 비교한다.

같은 key 값의 순서는 유지된다

sorted()와 list.sort()는 모두 안정 정렬을 보장한다. 안정 정렬은 key 값이 같은 요소끼리 기존의 상대적인 순서를 유지한다는 뜻이다.

items = [
    ("A", 90),
    ("B", 80),
    ("C", 90),
]

result = sorted(items, key=lambda item: item[1], reverse=True)
print(result)
# [('A', 90), ('C', 90), ('B', 80)]

A와 C의 점수는 같지만 입력에서 A가 먼저였으므로 결과에서도 먼저 나온다. reverse=True를 사용해도 같은 키를 가진 요소의 상대 순서는 유지된다.

어떤 것을 선택해야 할까

sorted를 선택하는 경우

  • 원본 데이터를 보존해야 할 때
  • 정렬 전후 값을 함께 사용해야 할 때
  • 튜플, 문자열, 집합, 제너레이터처럼 리스트가 아닌 iterable을 정렬할 때
  • 함수의 반환값으로 정렬 결과를 바로 넘기고 싶을 때
def top_scores(scores):
    return sorted(scores, reverse=True)

입력값을 바꾸지 않는 함수는 호출하는 쪽에서 결과를 예측하기 쉽다. 특히 다른 코드에서도 같은 리스트를 참조하고 있다면 원본 보존 여부를 명확히 결정해야 한다.

list.sort를 선택하는 경우

  • 이후에 원래 순서가 필요 없을 때
  • 현재 리스트를 정렬된 상태로 계속 사용할 때
  • 큰 리스트를 다루면서 새 리스트 생성을 피하고 싶을 때
scores = [82, 95, 71, 88]
scores.sort(reverse=True)

print(scores)  # [95, 88, 82, 71]

list.sort()는 정렬을 위해 내부 작업 공간을 사용할 수 있지만, 적어도 정렬 결과를 담는 별도의 리스트를 만들지는 않는다. 다만 원본 순서를 잃기 때문에 메모리만 보고 무조건 선택하기보다 데이터의 사용 흐름을 먼저 확인하는 편이 안전하다.

복사 후 sort와 sorted는 어떻게 다를까

원본을 보존하면서 sort()를 쓰고 싶다면 리스트를 먼저 복사할 수 있다.

numbers = [3, 1, 4, 2]

copied = numbers.copy()
copied.sort()

print(numbers)  # [3, 1, 4, 2]
print(copied)   # [1, 2, 3, 4]

동작 목적은 sorted(numbers)와 비슷하지만, 단순히 정렬된 복사본이 필요한 상황이라면 sorted()가 더 짧고 의도가 잘 드러난다. 복사한 리스트에 정렬 외의 변경도 이어서 적용해야 한다면 copy()와 sort()를 나눠 쓰는 방식이 자연스럽다.

정리

sorted()와 list.sort()의 핵심 차이는 정렬 알고리즘보다 데이터 처리 방식이다.

  • sorted(iterable)은 원본을 유지하고 정렬된 새 리스트를 반환한다.
  • list.sort()는 리스트 자체를 정렬하고 None을 반환한다.
  • 두 방식 모두 key, reverse와 안정 정렬을 지원한다.
  • 원본 보존이 필요하면 sorted(), 현재 리스트를 바꿔도 된다면 list.sort()를 선택한다.

코드에서 가장 먼저 물어볼 질문은 “정렬한 뒤 원본 순서가 필요한가?”다. 이 한 가지를 기준으로 잡으면 두 방식을 혼동할 일이 크게 줄어든다.

반응형

댓글