[Rejected] PEP 265 - Sorting Dictionaries by Value
원문 링크: PEP 265 - Sorting Dictionaries by Value
상태: Rejected 유형: Standards Track 작성일: 08-Aug-2001
PEP 265 – 값(Value)으로 딕셔너리 정렬
1. 개요 (Abstract)
이 PEP는 딕셔너리에 “값(value)으로 정렬”하는 기능을 추가할 것을 제안합니다. 이 제안의 주된 이점은 현재 초보자가 이해하기 어렵고 모든 개발자가 구현하기 번거로운 일반적인 Python 숙어(idiom)에 대해 “batteries included (기본 제공)” 지원을 제공하는 것입니다.
2. BDFL의 결정 (BDFL Pronouncement)
이 PEP는 거부되었습니다 (Rejected). 그 이유는 Python 2.4에 sorted()
내장 함수가 도입되면서 이 기능의 필요성이 대부분 충족되었기 때문입니다.
예시:
- 값(value)을 기준으로 딕셔너리의 아이템을 정렬하려면:
>>> from operator import itemgetter >>> d = {'a':2, 'b':23, 'c':5, 'd':17, 'e':1} >>> sorted(d.items(), key=itemgetter(1), reverse=True) [('b', 23), ('d', 17), ('c', 5), ('a', 2), ('e', 1)]
- 값(value)을 기준으로 키(key)만 정렬하려면:
>>> sorted(d, key=d.__getitem__, reverse=True) ['b', 'd', 'c', 'a', 'e']
또한, Python 2.5의 heapq.nlargest()
함수는 가장 높은 값(value)을 가진 소수의 아이템만 찾는 일반적인 사용 사례를 해결합니다.
>>> from heapq import nlargest
>>> from operator import itemgetter
>>> d = {'a':2, 'b':23, 'c':5, 'd':17, 'e':1}
>>> nlargest(2, d.items(), itemgetter(1))
[('b', 23), ('d', 17)]
3. 도입 배경 (Motivation)
딕셔너리의 일반적인 사용 사례 중 하나는 발생 횟수를 세는 것입니다. 특정 key
가 처음 등장하면 d[key]
의 값을 1로 설정하고, 이후 등장할 때마다 값을 증가시킵니다. get()
메서드를 사용하면 이 작업을 간결하게 수행할 수 있습니다.
d[key] = d.get(key, 0) + 1
모든 발생 횟수를 센 후에는, 결과 딕셔너리를 발생 횟수(값) 순서대로 출력하는 경우가 많으며, 종종 가장 큰 값부터 출력합니다. 이는 딕셔너리의 아이템을 값(value)으로 정렬할 필요로 이어집니다.
Python에서 이를 수행하는 일반적인 방법은 다음과 같습니다.
d.items()
를 사용하여 딕셔너리의 아이템 리스트를 얻습니다.- 각 아이템 튜플의 순서를
(key, value)
에서(value, key)
로 바꿉니다 (반전시킵니다). - 리스트를 정렬합니다. Python은 튜플의 첫 번째 아이템을 기준으로 리스트를 정렬하므로, 이렇게 하면 (반전된) 아이템 리스트가 값(value)으로 정렬됩니다.
- 원한다면 리스트를 뒤집고, 튜플을 다시
(key, value)
로 되돌릴 수 있습니다. (하지만 대부분의 경우(value, key)
순서로도 충분합니다.)
예시:
>>> d = {'a':2, 'b':23, 'c':5, 'd':17, 'e':1}
>>> items = [(v, k) for k, v in d.items()] # (value, key) 튜플 리스트 생성
>>> items.sort() # 값으로 정렬
>>> items.reverse() # 내림차순으로 만들기 (가장 큰 값이 먼저 오도록)
>>> items = [(k, v) for v, k in items] # 다시 (key, value)로 변환
>>> items
[('b', 23), ('d', 17), ('c', 5), ('a', 2), ('e', 1)]
이 방법은 작동하지만 두 가지 면에서 “사용하기 어렵습니다”.
- 이 숙어(idiom)는 숙련된 Python 개발자에게는 알려져 있지만, 초보자에게는 그 알고리즘(아이템 튜플 순서 반전)이나 구현 방식(고급 기능인 리스트 컴프리헨션 사용) 면에서 전혀 분명하지 않습니다.
- 반복적으로 많은 “번거로운(grunge)” 코드를 입력해야 하므로, 지루하고 실수를 유발할 수 있습니다.
따라서 PEP 265는 Python이 초보자가 이해하기 쉽고(또는 이해할 필요조차 없이) 모든 사용자가 사용하기 쉬운, 딕셔너리를 값(value)으로 정렬하는 방법을 제공하기를 원했습니다.
4. 제안된 해결책 (Rationale)
팀 피터스(Tim Peters)가 지적했듯이, 이 종류의 문제는 “모든 사람에게 모든 것이 되려”는 문제를 야기합니다. 따라서, PEP는 범위를 제한하여 “적절한 지점(sweet spot)”을 목표로 삼으려 했습니다. 특이한 경우(예: 사용자 정의 비교 함수를 통한 정렬)는 기존 방법을 사용하여 “수동으로” 처리할 수 있습니다.
몇 가지 간단한 가능성들이 논의되었습니다.
4.1. items()
메서드에 파라미터 추가
딕셔너리의 items()
메서드에 새 파라미터를 추가하여 완전한 하위 호환성을 유지할 수 있습니다.
- (1)
items(sort_by_values=0, reversed=0)
- (2)
items(sort_by_values=0)
: 리스트를 뒤집는 것은 충분히 쉽기 때문에reversed
파라미터는 생략할 수 있습니다.
또는 items()
가 단순히 (key, value)
순서를 제어하게 할 수 있습니다.
- (3)
items(values_first=0)
: 이 방식은 다른 방식보다 적은 작업을 수행하지만, 값으로 정렬 문제에서 가장 복잡하고 까다로운 부분인 아이템 튜플의 순서를 반전시키는 것을 용이하게 합니다. 사용 예시:items = d.items(1) # (value, key) 순서로 아이템을 가져옴 items.sort() items.reverse() # (원하는 경우)
이 세 가지 접근 방식의 주요 단점은 파라미터가 없는
items()
호출 시 기본 파라미터 처리에 따른 추가 오버헤드입니다. (하지만items()
가 주로 값으로 정렬된 리스트를 생성하는 데 사용된다고 가정하면 실제로는 단점이 아닐 수 있습니다.)
4.2. 새로운 딕셔너리 메서드 추가
“정렬”을 구현하는 새로운 딕셔너리 메서드를 추가하는 대안도 있습니다. 이 접근 방식은 두 가지 이점을 제공합니다.
items()
메서드에 오버헤드를 추가하는 것을 방지합니다.- 초보자에게 더 접근하기 쉽습니다. 딕셔너리를 정렬하는 메서드를 찾을 때 이 메서드를 발견하고, 값으로 정렬을 달성하기 위해 튜플 반전 및 리스트 정렬의 미묘한 부분을 이해할 필요가 없습니다.
키/값으로 정렬하고 오름차순/내림차순으로 정렬하는 네 가지 기본 가능성을 허용하기 위해 다음과 같은 메서드를 추가할 수 있습니다.
- (4)
sorted_items(by_value=0, reversed=0)
: 가장 일반적인 경우는by_value=1, reversed=1
일 것으로 예상되지만, 여기 제시된 기본값은 사용자에게 혼란을 줄 가능성이 적을 것입니다.sorted_items()
는items()
뒤에sort()
를 호출하는 것과 동일하게 작동할 것입니다.
마지막으로 (최후의 수단으로) 다음을 사용할 수도 있습니다.
- (5)
items_sorted_by_value(reversed=0)
5. 구현 (Implementation)
제안된 딕셔너리 메서드들은 C로 구현될 필요가 있을 것입니다. 구현은 Python의 기존 메커니즘에 몇 가지 호출을 추가하는 것에 불과하므로 상당히 간단할 것으로 예상됩니다.
6. 우려 사항 (Concerns)
가능성 1부터 3에서 이미 다루었던 런타임 오버헤드를 제외하고, 이 제안에 대한 우려 사항은 아마도 “기능 비대화(feature bloat)” 및/또는 “코드 비대화(code bloat)” 범주에 속할 것입니다. 하지만 PEP 작성자는 여기에 제시된 몇 가지 제안이 매우 최소한의 비대화를 초래하여, 비대화와 “부가 가치(value added)” 사이의 좋은 균형점을 찾을 것이라고 믿었습니다.
팀 피터스(Tim Peters)는 이 기능을 C로 구현하는 것이 오늘날 Python으로 구현하는 것보다 크게 빠르지 않을 수 있다고 언급했습니다. 그러나 여기서 의도된 주요 이점은 “접근성”과 “사용 용이성”이지 “속도”가 아닙니다. 따라서 (일반적인 items()
의 경우) 눈에 띄게 느려지지 않는 한 속도는 고려 사항이 아닐 수 있습니다.
7. 참고 자료 (References)
2001년 8월 comp.lang.python에서 “counting occurrences”라는 관련 스레드가 있었습니다. 여기에는 재사용 가능한 Python 함수 및 클래스로 구현하여 값으로 정렬 문제를 체계화하는 접근 방식의 예시가 포함되어 있습니다.
8. 저작권 (Copyright)
이 문서는 퍼블릭 도메인(public domain)에 공개되었습니다.
⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.
Comments