OS: MAC
참고: 👉 점프 투 파이썬 - 라이브러리 예제 바로가기
029. 순서대로 좌표를 정렬하려면?―functools.cmp_to_key(캄프투키)
- 직접 만든 비교 함수를 정렬 키 함수로 바꿔주는 도구. 좌표, 다중 조건, 사용자 정의 객체 정렬에서 매우 유용.
| 구분 | 내용 | 예시 | 결과 |
| 모듈 | 고차 함수(함수를 다루는 함수)를 담은 내장 라이브러리 |
import functools(펑터스) | — |
| 기능 요약 |
비교 함수(cmp)를 정렬 키 함수(key) 로 변환해 복잡한 정렬 기준 구현 |
sorted(iterable, key=functools.cmp_to_key(compare_func)) # 음수: 첫 번째 값이 더 작다 → 앞으로, 0 : 두 값이 같다. 양수: 첫 번째 값이 더 크다 → 뒤로 |
— |
| 예시① | 좌표를 (x, y) 순서로 오름차순 정렬 | import functools def compare(p1, p2): if p1[0] != p2[0]: return p1[0] - p2[0] else: return p1[1] - p2[1] points = [(3,4),(1,2),(3,2),(2,5)] result = sorted(points, key=functools.cmp_to_key(compare)) print(result) |
[(1, 2), (2, 5), (3, 2), (3, 4)] |
| 예시② | 숫자를 큰 순서대로(내림차순) 정렬 | import functools def compare(a, b): return b - a nums = [5,2,9,1,7] result = sorted(nums, key=functools.cmp_to_key(compare)) print(result) |
[9, 7, 5, 2, 1] |
| 예시③ | 문자열 길이 기준으로 정렬 | import functools def compare_len(a, b): return len(a) - len(b) words = ['apple','kiwi','banana','pear'] result = sorted(words, key=functools.cmp_to_key(compare_len)) print(result) |
['kiwi', 'pear', 'apple', 'banana'] |
라이브러리 예제 문제:



030. 웹 페이지를 임시로 저장하려면? ― functools.lru_cache
- lru_cache는 같은 인자에 대한 함수 결과를 자동 저장해, 다음 호출을 즉시 반환하게 하는 초간단 성능 부스트 데코레이터.
- I/O(웹, DB) 처럼 느린 작업 결과를 인자값만으로 결정할 수 있으면 효과가 큼.
- 결과가 자주 바뀌는 API라면: maxsize를 작게, 주기적으로 cache_clear() 호출 or 응답에 버전/타임스탬프를 인자로 포함해 캐시 갱신 제어.
- 입력이 리스트·딕셔너리처럼 해시 불가 타입이면 튜플/프리즈딕트 등 해시 가능한 형태로 변환해 인자로 넘겨야 함.
| 구분 | 내용 | 예시 | 결과 |
| 모듈 | 표준 라이브러리의 메모이제이션(결과 캐싱) 데코레이터 | from functools(펑터스) import lru_cache(엘-알-유 캐시) | — |
| 기본 문법 |
함수 호출 결과를 인자값 기준으로 캐시 |
from functools import lru_cache @lru_cache() def get(url): # 실제론 requests.get(url).text 등 return f"{url}의 HTML" |
같은 url로 다시 호출하면 계산/요청 생략, 캐시에서 즉시 반환 |
| 웹 요청 캐싱 (모의) |
최초만 “느림”, 이후 “빠름” |
import time from functools import lru_cache @lru_cache(maxsize=128) def fetch(url): time.sleep(1) # 느린 I/O 가정 return f"DATA: #실제 url 주소 입력 {url}" fetch("a") # 1초 fetch("a") # 즉시(캐시) |
첫 호출: 약 1초 ⏳ → 이후 동일 인자: 즉시 ⚡ |
| maxsize | 캐시 크기(항목 수) 제한. 초과 시 LRU부터 삭제 |
@lru_cache(maxsize=2) | 3개 키를 번갈아 호출하면 가장 오래 안 쓴 항목부터 제거 |
| typed | 1과 1.0을 다른 인자로 취급 |
@lru_cache(typed=True) | f(1)과 f(1.0)이 별도로 캐시됨 |
| 캐시 상태 확인 | 적중/미스/현재용량 등 통계 |
info = fetch.cache_info() # CacheInfo(hits=1, misses=1, maxsize=128, currsize=1) |
적중/미스 수를 숫자로 확인 가능 |
| 캐시 비우기 |
특정 함수의 캐시 전부 삭제 | fetch.cache_clear() | 다음 호출은 다시 계산/요청 수행 |
| 키 포인트 | 순수 함수(부작용/외부상태 의존 적음)에 적합 | — | 요청 결과가 자주 재사용될 때 성능 큰 폭 개선 |
라이브러리 예제 문제:


031. 기존 함수로 새로운 함수를 만들려면? ― functools.partial(파셜)
- 함수 일부 인자를 고정해 새 함수로 만드는 도구
- 기본값을 매번 반복해서 전달하지 않아도 됨. 콜백 함수, GUI 버튼, 스레드 등에 자주 활용됨
| 구분 | 내용 | 예시 | 결과 |
| 모듈 | 기존 함수를 “부분 적용”하여 새로운 함수 생성 |
import functools(펑터스) | — |
| 기능 요약 |
일부 인수를 미리 고정한 새 함수를 만들 때 사용 → 매번 같은 인수를 넣지 않아도 됨 |
functools.partial(함수명, 고정인자) | — |
| 기본 문법 |
functools.partial (func, *args, **kwargs) 기존 함수 func의 일부 인자를 미리 지정해 고정시킴 |
double = functools.partial(pow, exp=2) double(3) |
9 |
| 예시① | 숫자를 제곱하는 함수 미리 정의 | import functools pow2 = functools.partial(pow, exp=2) print(pow2(5)) |
25 |
| 예시② | 문자열 왼쪽 정렬 함수 | import functools align_left = lambda s: s.ljust(10, '*') print(align_left('Hi')) |
Hi******** |
| 예시③ | 웹 요청 기본 주소 고정 | import functools fetch = functools.partial(print, "요청 URL:") fetch("https://example.com") |
요청 URL: https://example.com |
라이브러리 예제 문제:


032. 함수를 적용하여 하나의 값으로 줄이려면? ― functools.reduce
- 반복 가능한 데이터를 누적해서 하나의 값으로 만든다
| 항목 | 설명 | 예시 | 결과 |
| 기능 요약 | 여러 개의 값을 누적 계산하여 하나의 값으로 축약 (reduce) 하는 함수 |
reduce(함수, iterable[, 초기값]) | - |
| 모듈 위치 | functools 모듈 안에 포함 | from functools import reduce | - |
| 필수 인자 | - 함수: 누적 계산에 사용할 함수 - iterable: 리스트, 튜플 등 반복 가능한 객체 |
from functools import reduce nums = [1, 2, 3, 4, 5] ① result = reduce(lambda x, y: x + y, nums) print(result) ② result2 = reduce(lambda x, y: x * y, nums) print(result2) # reduce(add, seq) → 누적 덧셈 reduce(mul, seq) → 누적 곱셈 |
① 15 ② 120 |
| 선택 인자 | 초기값: 누적 연산의 시작값을 지정할 수 있음 (없으면 첫 요소부터 시작) |
from functools import reduce reduce(lambda x, y: x + y, [1, 2, 3, 4, 5], 10) |
25 |
| 동작 과정 | [1, 2, 3, 4, 5] → (((1+2)+3)+4)+5 식으로 하나로 줄여감 |
lambda x, y: x + y | - |
| 대표 활용 예시 | 문자열 연결 | from functools import reduce w = ['ChatGPT', 'makes', 'coding', 'fun!'] s = reduce(lambda x, y: x + ' ' + y, w) print(s) # ''.join(iterable)도 자주 쓰이는 문자열 연결 방법 예) ''.join(['a', 'b', 'c']) > 'abc' |
ChatGPT makes coding fun! |
| 같이 쓰면 좋은 함수 | operator 모듈의 함수 (add, mul 등) |
from functools import reduce from operator import add, mul ① print(reduce(add, [10, 20, 30, 40])) ② print(reduce(mul, [2, 3, 4, 5])) # 곱 ③ print(reduce(add, [10, 20, 30], 100)) |
① 100 ② 120 ③ 160 |
라이브러리 예제 문제:


033. 래퍼 함수의 속성을 유지하려면? ― functools.wraps
- @wraps(func) = “데코레이터를 써도 원래 함수의 이름과 설명은 그대로 두자!”
| 구분 | 설명 | 예시 | 결과 |
| 기능 요약 | 래퍼(Wrapper) 함수가 원본 함수의 속성 (__name__, __doc__, 등) 을 그대로 유지하도록 해주는 데코레이터 |
@wraps(original_function) | 래퍼 함수도 원본 함수처럼 보이게 함 |
| 문제 상황 (wraps 사용 전) |
데코레이터를 쓰면 원래 함수 이름, 설명이 모두 래퍼 함수로 덮여버림 |
def outer(func): def wrapper(): print("실행 전") func() return wrapper @outer def hello(): """인사 함수""" print("안녕!") print(hello.__name__) print(hello.__doc__) |
wrapper None |
| 해결 방법 (wraps 사용 후) |
functools.wraps()로 원본 함수 정보를 복사 |
from functools import wraps def outer(func): @wraps(func) def wrapper(): print("실행 전") func() return wrapper @outer def hello(): """인사 함수""" print("안녕!") print(hello.__name__) print(hello.__doc__) |
![]() hello 인사 함수 |
| 보존되는 속성 | __name__, __doc__, __module__, __annotations__ 등 |
예: hello.__name__ → "hello" | 원본 함수 메타데이터 유지 |
| 필요 이유 | 디버깅, 로깅, 문서화(help()), 테스트 시 함수 이름/문서가 달라지면 혼란 발생 |
- | wraps로 일관성 유지 |
| 위치 | functools 모듈에 포함 | from functools import wraps | 표준 라이브러리 내장 |
라이브러리 예제 문제: add() 함수에 elapsed 데코레이터를 사용하더라도 함수 이름과 함수 설명문이 그대로 나오도록 하려면 어떻게 해야 할까?



034. 다양한 기준으로 정렬하려면? ― operator.itemgetter
| 구분 | 설명 | 예시 | 결과 |
| 기능 요약 | 객체(리스트, 튜플, 딕셔너리 등)에서 지정한 인덱스나 키의 값을 꺼내는 함수를 만들어 줌 | from operator import itemgetter get_second = itemgetter(1) print(get_second(('A', 10))) |
10 |
| 주 사용처 | sorted()나 list.sort()에서 정렬 기준(key) 으로 사용 |
from operator import itemgetter items = [('A', 2), ('C', 1), ('B', 3)] print(sorted(items, key=itemgetter(1)) # 두 번째 값(1) 오름차순 정렬 |
[('C', 1), ('A', 2), ('B', 3)] |
| 기본 문법 | itemgetter(n) 또는 itemgetter(n1, n2, ...) 형태 |
from operator import itemgetter data = ('x', 'y', 'z') print(itemgetter(0, 2)(data)) #0번째, 2번째 값 추출 |
('x', 'z') |
| 단일 기준 정렬 |
리스트의 한 인덱스를 기준으로 정렬 |
from operator import itemgetter people = [('길동', 30), ('영희', 25), ('철수', 35)] print(sorted(people, key=itemgetter(1))) # 나이순(1) 오름차순 정렬 |
[('영희', 25), ('길동', 30), ('철수', 35)] |
| 다중 기준 정렬 |
여러 인덱스를 기준으로 정렬할 수 있음 | from operator import itemgetter students = [('A', 2, 90), ('B', 1, 95), ('C', 1, 85)] print(sorted(students, key=itemgetter(1, 2))) # 두 번째 값(1) 오름차순 정렬 |
[('C', 1, 85), ('B', 1, 95), ('A', 2, 90)] |
| 딕셔너리 리스트 정렬 |
key 이름 기준으로 정렬 가능 | from operator import itemgetter users = [{'name': '철수', 'age': 30}, {'name': '영희', 'age': 25}] print(sorted(users, key=itemgetter('age'))) # 나이순('age') 오름차순 정렬 |
[{'name': '영희', 'age': 25}, {'name': '철수', 'age': 30}] |
| lambda 비교 |
lambda x: x[n] 과 같은 역할이지만 더 빠름 | from operator import itemgetter data = [('A', 3), ('B', 1), ('C', 2)] print(sorted(data, key=lambda x: x[1])) print(sorted(data, key=itemgetter(1))) # 학년(1) → 점수(2) 순 오름차순 정렬 |
[('B', 1), ('C', 2), ('A', 3)] |
| 복수 키 정렬 결과 |
itemgetter(1, 2)은 (x[1], x[2]) 튜플 반환 → 자동 비교 | from operator import itemgetter records = [(1, 2, 3), (1, 1, 5), (1, 2, 1)] print(sorted(records, key=itemgetter(1, 2))) # 두 번째 값(1) → 세 번째 값(2) 순 오름차순 정렬 |
[(1, 1, 5), (1, 2, 1), (1, 2, 3)] |
| 모듈 위치 | operator 모듈에 포함된 함수 | import operator print(operator.itemgetter) |
<class 'operator.itemgetter'> |
라이브러리 예제 문제:


'미래 먹거리를 위하여' 카테고리의 다른 글
| [파이썬 정복하기] 라이브러리 6장 - 파일과 디렉터리 다루기2 (맥OS 기준) ★ 파일 처리 관련 라이브러리 — filecmp, tempfile, glob (1) | 2025.11.13 |
|---|---|
| [파이썬 정복하기] 라이브러리 6장 - 파일과 디렉터리 다루기1 (맥OS 기준) ★ 라이브러리로 파일 다루기 — pathlib, os.path, fileinput 완전정리 (0) | 2025.11.12 |
| [파이썬 정복하기] 라이브러리 5장 - 함수형 프로그래밍 다루기1 (맥OS 기준) (0) | 2025.11.10 |
| [파이썬 정복하기] 라이브러리 4장 - 수학과 숫자 다루기 (맥OS 기준) (0) | 2025.11.09 |
| [파이썬 정복하기] 라이브러리 3장 - 다양한 데이터 다루기6 (맥OS 기준) (1) | 2025.11.08 |
