확인한 환경과 범위

Windows · Python 3.12.4. 본문의 첫 예제를 실행하여 표준 출력과 예상 결과가 일치함을 확인했습니다. 연습문제의 모든 입력을 검증한 것은 아닙니다.

이 글의 순서 4개 단락

작업 번호를 순서대로 정렬한 뒤 개수를 세려는데 TypeError가 발생할 수 있습니다. A = A.sort()에서 정렬된 목록이 A에 들어간다고 생각하기 쉽지만, 실제로 대입되는 값은 None입니다. Python 3.12에서 작업 번호 목록으로 이 과정을 살펴보겠습니다.

실패한 작업 목록과 오류 메시지

다음 예제의 입력은 코드에 직접 적은 작업 번호 목록입니다. 별도의 입력은 필요하지 않습니다. 오류를 관찰한 뒤 나머지 비교도 이어서 볼 수 있도록 TypeError를 잡아 메시지를 출력합니다.

A = [3, 1, 2, 1]
shared = A
A = A.sort()
print('대입 후 A:', A)
print('정렬된 원본:', shared)
try:
    print('작업 수:', len(A))
except TypeError as error:
    print('TypeError:', error)

jobs = [3, 1, 2, 1]
shared_jobs = jobs
jobs.sort()
print('sort 결과:', jobs)
print('같은 목록 참조:', shared_jobs)
print('같은 객체:', jobs is shared_jobs)

original = [3, 1, 2, 1]
ordered = sorted(original)
print('원래 순서:', original)
print('새 목록:', ordered)
print('같은 객체:', original is ordered)

empty = []
empty_result = empty.sort()
print('빈 목록 sort:', empty, empty_result)
print('빈 목록 sorted:', sorted(empty))

Python에서 A = A.sort()가 None이 되는 이유 — 첫 예제의 실제 실행 결과

예상 표준 출력은 다음과 같습니다.

대입 후 A: None
정렬된 원본: [1, 1, 2, 3]
TypeError: object of type 'NoneType' has no len()
sort 결과: [1, 1, 2, 3]
같은 목록 참조: [1, 1, 2, 3]
같은 객체: True
원래 순서: [3, 1, 2, 1]
새 목록: [1, 1, 2, 3]
같은 객체: False
빈 목록 sort: [] None
빈 목록 sorted: []

오류 메시지의 NoneType은 len()에 전달된 값이 리스트가 아니라 None임을 알려 줍니다. A.sort()가 먼저 원본 리스트를 정렬하고 None을 반환한 다음, 대입문이 A를 그 None에 연결합니다. shared는 대입 전의 리스트를 계속 참조하므로 정렬된 원본을 보여 줍니다. 예외를 잡지 않으면 len(A)에서 프로그램이 중단됩니다.

원본을 바꿀지 보존할지 선택하기

원래 목록의 순서를 바꿔도 된다면 jobs.sort()처럼 대입 없이 호출합니다. 이후에도 jobs는 정렬된 리스트를 가리킵니다. shared_jobs = jobs는 복사가 아니라 같은 리스트에 다른 이름을 붙이는 것이므로, shared_jobs에서도 바뀐 순서가 보입니다. is는 두 변수가 같은 객체를 가리키는지 확인합니다.

원래 순서가 필요하다면 ordered = sorted(original)을 사용합니다. sorted()는 정렬된 새 리스트를 반환하므로 original은 그대로이고 ordered만 정렬된 순서입니다. 새 리스트는 얕은 복사이므로, 원소가 변경 가능한 객체라면 그 원소 자체까지 복사되는 것은 아닙니다. 자세한 동작은 Python 리스트 자료형 문서와 sorted 문서를 참고하세요.

빈 목록과 중복값에서 확인할 점

빈 리스트에 sort()를 호출해도 오류는 나지 않으며 리스트는 빈 상태이고 반환값은 여전히 None입니다. 반면 sorted([])는 새 빈 리스트를 반환합니다. 중복된 작업 번호도 삭제되지 않습니다. 위 예제의 두 1은 모두 정렬 결과에 남습니다.

sort()는 리스트의 메서드이고 sorted()는 여러 종류의 반복 가능한 객체를 받을 수 있습니다. 다만 정렬 대상끼리 순서를 비교할 수 있어야 합니다. 예를 들어 Python 3.12에서 정수와 문자열을 섞은 [1, '2']를 기본 방식으로 정렬하면 TypeError가 발생합니다. 이 오류는 앞의 None에 len()을 호출한 오류와 원인이 다르므로 메시지와 오류가 난 줄을 함께 확인하세요.

연습: 원래 작업 순서 보존하기

tasks = [2, 1, 2]의 원래 순서는 그대로 두고 정렬한 목록을 ordered_tasks에 저장해 보세요. 두 목록과 같은 객체인지도 출력해 보세요.

풀이:

tasks = [2, 1, 2]
ordered_tasks = sorted(tasks)
print(tasks)
print(ordered_tasks)
print(tasks is ordered_tasks)

예상 출력은 다음과 같습니다. 두 2가 남고, 두 변수는 서로 다른 리스트를 가리킵니다.

[2, 1, 2]
[1, 2, 2]
False

CHECK THE SOURCE

참고한 공식 문서

기능 설명은 위 문서를 참고했으며, 예제의 입력·결과와 한계는 본문에 따로 기록했습니다.

한 줄씩 이해하고, 차곡차곡 기록합니다.이 글의 오류 제보하기 ↗