온라인 상점에 상품을 등록한 순서는 키보드, 마우스, 모니터인데 화면에는 가격이 싼 상품부터 보여 주고 싶다고 해 보겠습니다. 사람이 종이에 적힌 가격표 세 장을 정리한다면 각 가격을 보고 작은 금액부터 카드를 다시 놓습니다. 파이썬에서도 같은 일을 정렬이라고 합니다.
이때 처음 만나는 이름이 sorted, sort, key, lambda입니다. 네 단어를 이미 알고 있다고 가정하지 않고 하나씩 나누어 보겠습니다.
sorted(): 여러 값을 순서대로 정리한 새 리스트를 만들어 주는 파이썬 기본 함수입니다.sort(): 리스트 안의 값 순서를 그 리스트에서 직접 바꾸는 메서드입니다.key: 상품처럼 정보가 여러 개인 값에서 어느 부분을 비교할지 알려 주는 정렬 기준입니다.lambda: 짧은 함수를 이름 없이 한 줄로 만드는 문법입니다. 먼저 일반 함수를 배운 뒤 마지막에 같은 코드를 줄여 쓸 때 사용하겠습니다.
처음부터 네 가지를 한 줄에 넣으면 각 부분의 역할이 보이지 않습니다. 따라서 숫자 정렬로 sorted() 하나를 확인하고, 그다음 상품 가격을 꺼내는 일반 함수를 key에 연결한 뒤, 마지막에 그 함수를 lambda로 바꾸겠습니다.

확인한 환경
- Windows
- Python 3.9.13 직접 실행
- Python 3.14.7 공식 정렬 문서 확인
- 확인일 : 2026년 9월 1일
본문의 예제 6개를 직접 실행했습니다. 정상 예제에서는 원본 보존 여부, key 호출 횟수, 가격순과 복합 기준 정렬 결과를 확인했습니다. 마지막 예제에서는 숫자와 문자열을 그대로 비교할 때 발생하는 TypeError도 확인했습니다.
정렬은 값을 바꾸는 것이 아니라 순서를 정하는 일입니다
숫자 세 개가 아래 순서로 저장되어 있다고 하겠습니다.
[30, 10, 20]
오름차순 정렬은 작은 값부터 큰 값으로 놓는 것입니다.
[10, 20, 30]
여기서 30이 10으로 바뀐 것이 아닙니다. 세 숫자는 그대로 있고 놓인 위치만 달라졌습니다. 내림차순은 반대로 큰 값부터 작은 값으로 놓습니다.
[30, 20, 10]
정렬을 이해할 때는 두 가지를 구분해야 합니다.
- 어떤 값을 먼저 놓을지 판단하는 비교 기준
- 정리한 결과를 새 목록에 만들지, 기존 목록에서 바꿀지 정하는 저장 방식
key가 첫 번째를 담당하고, sorted()와 sort()의 차이가 두 번째에 해당합니다.
sorted는 파이썬이 기본으로 제공하는 정렬 함수입니다
함수는 값을 입력받아 정해진 작업을 하고 결과를 돌려주는 기능입니다. sorted()는 파이썬을 설치하면 바로 사용할 수 있는 기본 함수이며 형태는 다음과 같습니다.
sorted(정렬할 값들)
괄호 안에는 정렬할 목록을 넣습니다. sorted()는 그 값을 정렬한 뒤 새 리스트를 결과로 돌려줍니다. 원래 목록은 건드리지 않습니다.
입력 : [30, 10, 20]
처리 : 숫자를 작은 값부터 놓는다
출력 : [10, 20, 30]이라는 새 리스트
원본 : [30, 10, 20] 그대로 유지
첫 sorted 코드를 한 부분씩 읽어 봅니다
먼저 숫자 리스트로 두 방식의 차이를 보겠습니다.
numbers = [30, 10, 20]
sorted_numbers = sorted(numbers)
print("원본 :", numbers)
print("결과 :", sorted_numbers)
첫 줄의 numbers = [30, 10, 20]은 숫자 세 개를 리스트에 담고 그 리스트에 numbers라는 이름을 붙입니다.
둘째 줄은 오른쪽부터 읽습니다.
sorted_numbers = sorted(numbers)
numbers에 저장된[30, 10, 20]이sorted()의 입력으로 들어갑니다.sorted()가 숫자를 작은 값부터 정리합니다.- 정렬된 새 리스트
[10, 20, 30]을 결과로 돌려줍니다. - 등호 왼쪽의
sorted_numbers가 그 새 리스트를 저장합니다.
마지막 두 줄은 원래 리스트와 새 리스트를 각각 출력합니다. 둘을 함께 출력해야 원본이 유지됐는지 확인할 수 있습니다.
실행 결과는 다음과 같습니다.
원본 : [30, 10, 20]
결과 : [10, 20, 30]
sorted(numbers)는 정렬된 새 리스트를 반환합니다. 그래서 numbers에는 처음 순서가 그대로 남고, 반환값을 받은 sorted_numbers만 오름차순입니다.
sort는 새 리스트를 만들지 않고 원본을 직접 바꿉니다
sort()는 sorted()와 이름이 비슷하지만 사용하는 모양과 결과가 다릅니다.
sorted(numbers) : 파이썬 기본 함수에 numbers를 넣는다
numbers.sort() : numbers 리스트에 붙어 있는 sort 메서드를 실행한다
메서드는 어떤 값에 소속된 함수입니다. numbers.sort()에서 점 앞의 numbers가 작업 대상이고, 점 뒤의 sort()가 그 리스트에 수행할 작업입니다. 이 메서드는 새 리스트를 돌려주지 않고 numbers 안의 순서를 바로 바꿉니다.
numbers = [30, 10, 20]
result = numbers.sort()
print("원본 :", numbers)
print("반환값 :", result)
원본 : [10, 20, 30]
반환값 : None
None은 “돌려받은 값이 없다”는 뜻으로 사용하는 파이썬의 특별한 값입니다. sort()는 원본에서 정렬 작업을 끝냈기 때문에 별도의 새 리스트를 반환하지 않습니다. 따라서 다음처럼 작성하면 정렬된 리스트를 얻는 것이 아니라 변수에 None이 들어갑니다.
numbers = numbers.sort() # numbers가 None이 됨
원래 목록을 남겨야 하면 sorted(), 원본 순서를 바꿔도 되면 list.sort()를 선택하면 됩니다. sort()는 리스트에만 사용할 수 있지만 sorted()는 튜플, 세트 같은 반복 가능한 값도 받아 최종 결과를 리스트로 돌려줍니다.
| 필요한 결과 | 사용할 방식 | 원본 |
|---|---|---|
| 정렬된 새 리스트 | sorted(values) |
유지 |
| 현재 리스트 자체를 정렬 | values.sort() |
변경 |
파이썬 리스트 사용법에서 append(), remove(), sort()처럼 리스트를 직접 바꾸는 메서드를 함께 확인할 수 있습니다.
단순한 숫자는 값 자체가 비교 기준입니다
숫자 리스트에서는 파이썬이 숫자 자체를 비교하면 됩니다. 10 < 20처럼 어떤 값이 작은지 판단할 수 있기 때문입니다. 그래서 별도의 기준을 말하지 않아도 sorted(numbers)가 동작합니다.
하지만 상품 하나에는 이름과 가격이 함께 들어 있습니다. 상품을 이름순으로 놓을 수도 있고 가격순으로 놓을 수도 있습니다. 파이썬은 우리가 원하는 기준을 추측하지 않으므로 이때 key가 필요합니다.
key는 여러 정보 중 비교할 값을 고릅니다
상품 하나를 이름과 가격으로 묶어 보겠습니다.
products = [
{"name": "키보드", "price": 45000},
{"name": "마우스", "price": 25000},
{"name": "모니터", "price": 180000},
]
바깥쪽 대괄호는 상품 여러 개를 담은 리스트이고, 중괄호 한 쌍은 상품 하나를 나타내는 딕셔너리입니다. 각 상품에는 name과 price라는 두 정보가 있습니다.
첫 번째 상품 : 이름은 키보드, 가격은 45000
두 번째 상품 : 이름은 마우스, 가격은 25000
세 번째 상품 : 이름은 모니터, 가격은 180000
sorted(products)만 쓰면 파이썬은 상품 딕셔너리 전체를 비교하려고 합니다. 하지만 “키보드 상품 전체가 마우스 상품 전체보다 작다”는 규칙은 없으므로 TypeError가 발생합니다.
우리가 원하는 일은 다음과 같습니다.
상품 전체를 비교하지 않는다
→ 상품마다 price 값만 꺼낸다
→ 45000, 25000, 180000을 비교한다
→ 작은 가격을 가진 원래 상품부터 놓는다
이때 key는 파이썬 딕셔너리의 키라는 뜻으로 쓰인 것이 아니라, sorted()에 정렬 기준을 만드는 함수를 전달하는 매개변수 이름입니다.
key에 연결할 함수부터 만들어 봅니다
먼저 기준값을 꺼내는 일반 함수를 만들어 보겠습니다.
def get_price(product):
return product["price"]
sorted_products = sorted(products, key=get_price)
for product in sorted_products:
print(product["name"], product["price"])
아직 lambda는 사용하지 않았습니다. 먼저 get_price()가 상품 하나를 받아 가격 하나를 돌려주는 과정만 보겠습니다.
def get_price(product):
return product["price"]
product: 함수에 들어오는 상품 딕셔너리 하나입니다.product["price"]: 그 상품에서price라는 이름의 값을 꺼냅니다.return: 꺼낸 가격을 함수의 결과로 돌려줍니다.
키보드 상품을 직접 넣는다면 결과는 45000입니다.
입력 : {"name": "키보드", "price": 45000}
처리 : "price"에 저장된 값을 찾는다
출력 : 45000
마우스 25000
키보드 45000
모니터 180000
이제 핵심 줄을 부분별로 읽어 보겠습니다.
sorted_products = sorted(products, key=get_price)
products: 정렬할 원본 목록입니다.key=: 뒤에 적은 함수를 사용해 각 원소의 비교 기준을 만들라는 뜻입니다.get_price: 상품에서 가격을 꺼내는 함수입니다.sorted_products: 정렬이 끝난 새 리스트를 저장할 변수입니다.
key=get_price에는 괄호가 없습니다. 지금 함수를 한 번 실행하는 것이 아니라, sorted()가 상품을 하나씩 넣어 실행할 수 있도록 함수 자체를 건네는 것이기 때문입니다.
key=get_price : 함수를 sorted에 건넨다
key=get_price() : 지금 함수를 실행하려 한다. product 입력이 없어 오류가 난다
get_price({"name": "키보드", "price": 45000}) → 45000
get_price({"name": "마우스", "price": 25000}) → 25000
get_price({"name": "모니터", "price": 180000}) → 180000
파이썬은 오른쪽의 45000, 25000, 180000을 비교해 순서를 정한 뒤, 숫자만 반환하는 것이 아니라 원래 상품 딕셔너리를 그 순서대로 배치합니다. 상품 카드에서 가격표를 잠깐 꺼내 나란히 비교한 뒤 카드를 가격순으로 다시 놓는 모습과 같습니다.
중요한 점은 key 함수가 상품을 가격으로 바꾸지 않는다는 것입니다. 정렬이 끝난 결과에는 여전히 이름과 가격이 모두 들어 있는 상품 딕셔너리가 남습니다. 가격은 순서를 판단할 때만 사용됩니다.
key 함수는 원소마다 한 번 호출됩니다
호출 시점을 눈으로 확인하기 위해 기준 함수 안에 print()를 넣었습니다.
products = [
{"name": "키보드", "price": 45000},
{"name": "마우스", "price": 25000},
{"name": "모니터", "price": 180000},
]
def get_price(product):
print("기준값 추출 :", product["name"], "→", product["price"])
return product["price"]
sorted_products = sorted(products, key=get_price)
print("정렬 결과 :", [product["name"] for product in sorted_products])
기준값 추출 : 키보드 → 45000
기준값 추출 : 마우스 → 25000
기준값 추출 : 모니터 → 180000
정렬 결과 : ['마우스', '키보드', '모니터']
상품이 세 개이므로 get_price()도 세 번 호출됐습니다. 공식 정렬 문서에서도 key 함수는 입력 원소마다 정확히 한 번 호출된다고 설명합니다. 비교할 때마다 딕셔너리에서 가격을 다시 꺼내는 것이 아니라 기준값을 먼저 준비하고 정렬하는 방식입니다.

여기까지 이해한 뒤 lambda로 한 줄을 줄입니다
lambda는 이름을 붙이지 않고 짧은 함수를 만드는 파이썬 문법입니다. 새로운 정렬 기능이 아니라, 방금 만든 get_price() 함수를 더 짧게 적는 방법입니다.
먼저 두 모양을 나란히 보겠습니다.
def get_price(product):
return product["price"]
lambda product: product["price"]
두 코드는 모두 상품 하나를 입력받아 가격 하나를 돌려줍니다. lambda에서는 def, 함수 이름, return을 생략하고 콜론 왼쪽에 입력값, 오른쪽에 돌려줄 값을 적습니다.
lambda product: product["price"]
입력값 : 반환할 값
이제 이 짧은 함수를 key에 넣습니다.
sorted_products = sorted(
products,
key=lambda product: product["price"],
)
sorted()가 상품 하나를 product에 넣으면, 람다는 그 상품의 가격을 반환합니다. 람다가 정렬하는 것이 아닙니다. 람다는 기준값만 꺼내고, 실제 순서 결정은 sorted()가 담당합니다.
처음 연습할 때는 lambda를 외우려고 하지 않아도 됩니다. get_price()의 입력과 출력이 이해된 뒤 두 코드가 같은 역할이라는 것을 확인하는 순서가 좋습니다. 기준이 복잡하거나 여러 곳에서 다시 쓸 함수라면 이름 있는 def가 읽기 쉽고, 한 번만 쓰는 짧은 기준이라면 lambda로 가까이 붙여 쓸 수 있습니다.
reverse는 기준을 바꾸지 않고 방향만 뒤집습니다
가격이 비싼 상품부터 보고 싶다면 reverse=True를 추가합니다.
expensive_first = sorted(
products,
key=lambda product: product["price"],
reverse=True,
)
for product in expensive_first:
print(product["name"], product["price"])
모니터 180000
키보드 45000
마우스 25000
key는 여전히 가격을 꺼냅니다. reverse=True가 최종 정렬 방향만 내림차순으로 바꿉니다. 가격에 마이너스를 붙이는 방식도 가능하지만, 단순 내림차순은 reverse=True가 의도를 더 바로 보여줍니다.
여기부터는 기본 원리를 이해한 뒤 보는 응용입니다
가격 하나로 정렬하는 데 성공했다면 핵심은 끝났습니다. 다음 두 부분은 같은 가격의 상품을 다시 이름순으로 놓거나, 같은 기준값의 원래 순서가 어떻게 되는지 궁금할 때 읽으면 됩니다.
기준이 같으면 두 번째 기준을 튜플로 넣습니다
가격이 같은 상품 두 개가 있을 때 이름순까지 정하려면 key가 튜플을 반환하게 만들 수 있습니다.
products = [
{"name": "키보드", "price": 45000},
{"name": "마우스", "price": 25000},
{"name": "웹캠", "price": 45000},
{"name": "모니터", "price": 180000},
]
sorted_products = sorted(
products,
key=lambda product: (product["price"], product["name"]),
)
for product in sorted_products:
print(product["name"], product["price"])
마우스 25000
웹캠 45000
키보드 45000
모니터 180000
튜플은 첫 번째 값부터 비교합니다. 먼저 가격을 비교하고, 가격까지 같을 때만 두 번째 값인 이름을 비교합니다.
(가격, 이름)
1차 2차
한글 문자열의 기본 정렬은 사전에서 기대하는 발음 순서가 아니라 유니코드 코드 포인트 순서를 따릅니다. 위 예제에서는 실행 결과를 그대로 보여주지만, 사람 이름이나 상품명을 실제 사전식 순서로 정렬해야 하는 서비스라면 언어별 정렬 규칙을 별도로 적용해야 합니다.
기준값이 같으면 기존 순서는 유지됩니다
파이썬 정렬은 안정 정렬입니다. key가 같은 값을 돌려준 원소끼리는 입력 목록에서 먼저 있던 순서가 유지됩니다.
orders = [
{"id": "A", "amount": 3000},
{"id": "B", "amount": 1000},
{"id": "C", "amount": 3000},
]
sorted_orders = sorted(orders, key=lambda order: order["amount"])
print([order["id"] for order in sorted_orders])
['B', 'A', 'C']
A와 C의 금액은 같지만 원래 A가 앞에 있었으므로 정렬 후에도 A, C 순서입니다. 같은 가격 상품의 등록 순서를 유지해야 할 때 이 성질을 이용할 수 있습니다.
숫자와 문자열이 섞이면 먼저 자료형을 맞춰야 합니다
다음 목록에는 정수 10과 문자열 "20"이 섞여 있습니다.
values = [10, "20", 3]
print(sorted(values))
Python 3에서는 숫자와 문자열의 크기를 바로 비교하지 않으므로 다음 오류가 발생합니다.
TypeError: '<' not supported between instances of 'str' and 'int'

숫자로 저장해야 할 값이라면 입력 단계에서 모두 int로 바꾸는 편이 자연스럽습니다.
values = [10, "20", 3]
numbers = [int(value) for value in values]
print(sorted(numbers))
[3, 10, 20]
화면 표시용 문자열로 정렬하려는 목적이라면 key=str처럼 문자열 기준을 명시할 수도 있습니다. 다만 "10", "2", "20"은 숫자 크기가 아니라 글자 순서로 비교되므로 결과가 기대와 다를 수 있습니다. 데이터가 숫자인지 글자인지 먼저 결정한 뒤 자료형을 맞추는 것이 안전합니다. 파이썬 자료형 기초에서 숫자 10과 문자열 "10"이 다른 이유를 이어서 확인할 수 있습니다.
정렬 코드는 이렇게 읽으면 됩니다
아래 코드를 보면 세 부분으로 나누어 읽어 보세요.
sorted(products, key=lambda product: product["price"], reverse=True)
products : 무엇을 정렬할지
lambda product: product["price"] : 무엇을 기준으로 비교할지
reverse=True : 어느 방향으로 놓을지
key 함수는 각 원소에서 비교용 값을 하나씩 꺼내고, 정렬 함수는 그 기준값의 순서대로 원래 원소를 배치합니다. 원본이 필요하면 sorted(), 원본 리스트를 직접 바꿔도 되면 sort()를 사용하면 됩니다.
처음 연습할 때는 lambda부터 줄여 쓰지 말고 get_price()처럼 이름 있는 함수로 기준값을 출력해 보세요. 원소 하나가 함수에 들어가 어떤 값으로 바뀌는지 보이면, 딕셔너리 목록과 튜플 목록의 정렬 코드도 같은 원리로 읽을 수 있습니다.
관련 글
- 파이썬 enumerate와 zip 사용법 : 번호와 두 리스트를 함께 꺼내기
- 파이썬 딕셔너리 사용법 : KeyError를 get으로 막는 가장 쉬운 방법
- 파이썬 리스트 컴프리헨션 : for문 한 줄의 순서와 if 위치
참고한 공식 문서
'IT프로그래밍 > 파이썬' 카테고리의 다른 글
| 파이썬 import 사용법 : 직접 만든 모듈에서 함수 불러오기 (0) | 2026.09.07 |
|---|---|
| 파이썬 ModuleNotFoundError 해결 : pip와 실행 Python 경로 맞추기 (0) | 2026.09.04 |
| 파이썬 t-string 사용법 : f-string과 다른 점과 Python 3.14 처리 원리 (0) | 2026.09.02 |
| 파이썬 enumerate와 zip 사용법 : 번호와 두 리스트를 함께 꺼내기 (0) | 2026.08.26 |
| 파이썬 리스트 컴프리헨션 : for문 한 줄의 순서와 if 위치 (0) | 2026.08.21 |
| 파이썬 파일 읽기 쓰기 : with open으로 주문장을 남기는 방법 (0) | 2026.08.20 |
| 파이썬 try except 사용법 : ValueError와 KeyError 예외 처리 (0) | 2026.08.20 |
| 파이썬 set 사용법 : 리스트 중복 제거와 순서 유지 방법 (0) | 2026.08.18 |
댓글