[Python] 자주 사용되는 표준 라이브러리
표준 라이브러리란?
특정한 프로그래밍 언어에서 자주 사용되는 표준 소스코드를 미리 구현해 놓은 라이브러리. 파이썬 표준 라이브러리는 다음 공식 문서에서 자세히 확인할 수 있다.
The Python Standard Library
While The Python Language Reference describes the exact syntax and semantics of the Python language, this library reference manual describes the standard library that is distributed with Python. It...
docs.python.org
목차
- 내장 함수
- 기본 입출력 함수부터 정렬 함수까지 기본적인 함수들을 제공
- itertools
- 파이썬에서 반복되는 형태의 데이터를 처리하기 위한 유용한 기능들을 제공
- 특히 순열과 조합 라이브러리가 자주 사용됨
- heapq
- 힙(Heap) 기능을 제공하는 라이브러리
- 우선순위 큐 기능을 구현하기 위해 사용함
- bisect
- 이진 탐색(Binary Search) 기능을 제공
- collections
- 덱(deque), 카운터(Counter) 등의 유용한 자료구조를 포함
- math
- 필수적인 수학적 기능을 제공
- 팩토리얼, 제곱근, 최대공약수(GCD), 삼각함수 관련 함수부터 파이(pi)와 같은 상수를 포함
내장 함수
# sum()
# 리스트와 같은 iterable 객체*가 입력으로 주어졌을 때, 모든 원소의 합을 반환
result = sum([1, 2, 3, 4, 5])
print(result)
# 15
# min(), max()
# 함수 파라미터가 2개 이상 들어왔을 때 가장 작은 또는 가장 큰 값을 반환
min_result = min(7, 3, 5, 2)
max_result = max(7, 3, 5, 2)
print(min_result, max_result)
# 2 7
# eval()
# 수학 수식이 문자열 형식으로 들어오면 해당 수식을 계산한 결과를 반환
result = eval("(3+5)*7")
print(result)
# 56
# sorted()
# iterable 객체가 들어왔을 때, 정렬된 결과를 반환
result = sorted([9, 1, 8, 5, 4])
reverse_result = sorted(result, reverse = True)
print(result)
print(reverse_result)
# [1, 4, 5, 8, 9]
# [9, 8, 5, 4, 1]
# sorted() with key
# key 속성으로 정렬 기준을 명시할 수 있으며,
# reverse 속성으로 정렬된 결과 리스트를 뒤집을지의 여부를 설정
array = [('홍길동', 35), ('이순신', 75), ('아무개', 50)]
result = sorted(array, key = lambda x : x[1], reverse = True)
print(result)
# [('이순신', 75), ('아무개', 50), ('홍길동', 35)
* 파이썬에서 iterable 객체는 반복 가능한 객체를 말한다. 리스트, 사전 자료형, 튜플 자료형 등이 이에 해당한다.
itertools
모든 경우의 수를 고려해야 할 때, 어떤 라이브러리를 효과적으로 사용할 수 있을까?
순열
n개 중에서 r를 뽑아서 줄을 세우는 것 $_{n}P_{r}$
순열과 조합 - 순열이란
순열과 조합은 경우의 수 공식 - 대표 뽑기에서 했던 건데 조금 더 자세히 알아볼게요. 순열과 조합은 조금 어려운 내용이라서 공부하기 힘들 거예요. 계산 자체가 어렵다기보다는 순열인지 조
mathbang.net
ex) ['A', 'B', 'C']에서 세 개를 선택하여 나열하는 경우
ABC ACB
BAC BCA
CAB CBA
# 순열
from itertools import permutations
data = ['A', 'B', 'C']
result = list(permutations(data, 3))
print(result)
# 출력
# [('A', 'B', 'C'), ('A', 'C', 'B'),
# ('B', 'A', 'C'), ('B', 'C', 'A'),
# ('C', 'A', 'B'), ('C', 'B', 'A')]
# 중복 순열
from itertools import product
data = ['A', 'B', 'C']
# 2개를 뽑는 모든 순열 구하기 (중복 허용)
result = list(product(data, repeat = 2))
print(result)
# 출력
# [('A', 'A'), ('A', 'B'), ('A', 'C'),
# ('B', 'A'), ('B', 'B'), ('B', 'C'),
# ('C', 'A'), ('C', 'B'), ('C', 'C')]
조합
서로 다른 n개에서 순서와 상관없이 r를 고르는 것 $_{n}C_{r}$
순열과 조합 - 조합이란
순열에 이어 조합이에요. 조합과 순열은 너무 비슷해서 구분하기 어려워요. 정확히 말하면 문제를 푸는 식이 특별히 어려운 게 아닌데 서술형으로 된 문제를 읽고 순열로 풀어야 하는지 조합으
mathbang.net
ex) ['A', 'B', 'C']에서 순서를 고려하지 않고 두 개를 뽑는 경우
AB
AC
BC
# 조합
from itertools import combinations
data = ['A', 'B', 'C']
result = list(combinations(data, 2))
print(result)
# 출력
# [('A', 'B'), ('A', 'C'), ('B', 'C')]
# 중복 조합
from itertools import combinations_with_replacement
data = ['A', 'B', 'C']
# 2개를 뽑는 모든 조합 구하기 (중복 허용)
result = list(combinations_with_replacement(data, 2))
print(result)
# 출력
# [('A', 'A'), ('A', 'B'), ('A', 'C'),
# ('B', 'B'), ('B', 'C'), ('C', 'C')]
heapq
heapq는 다익스트라 최단 경로 알고리즘을 포함해 다양한 알고리즘에서 우선순위 큐 기능을 구현하고자 할 때 사용된다.
파이썬의 힙은 최소 힙(Min Heap)으로 구성되어 있으므로, 단순히 원소를 힙에 전부 넣었다 빼는 것만으로도 시간 복잡도 $O(nlogn)$ 에 오름차순 정렬이 완료된다. 보통 최소 힙 자료구조의 최상단 원소는 항상 '가장 작은' 원소이기 때문이다.
힙에 원소를 삽입할 때는 heapq.heappush() 메서드를 이용하고, 힙에서 원소를 꺼내고자 할 때는 heapq.heappop() 메서드를 이용한다.
# 최소 힙
import heapq
def heapsort(iterable):
h = []
result = []
# 모든 원소를 차례대로 힙에 삽입
for value in iterable:
heapq.heappush(h, value)
# 힙에 삽입된 모든 원소를 차례대로 꺼내어 담기
for i in range(len(h)):
result.append(heapq.heappop(h))
return result
result = heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])
print(result)
# 출력
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
하지만, 파이썬에서는 최대 힙(Max Heap)을 제공하지 않으므로, heapq 라이브러리를 이용해 최대 힙을 구현해야 할 때는 원소의 부호를 임시로 변경하는 방식을 사용한다.
힙에 원소를 삽입하기 전에 잠시 부호를 반대로 바꾸었다가, 힙에서 원소를 꺼낸 뒤에 다시 원소의 부호를 바꾸면 된다.
# 최대 힙
import heapq
def heapsort(iterable):
h = []
result = []
# 모든 원소를 차례대로 힙에 삽입
for value in iterable:
heapq.heappush(h, value * -1)
# 힙에 삽입된 모든 원소를 차례대로 꺼내어 담기
for i in range(len(h)):
result.append(heapq.heappop(h) * -1)
return result
result = heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])
print(result)
# 출력
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
bisect
파이썬에서는 이진 탐색을 쉽게 구현할 수 있도록 bisect 라이브러리를 제공한다. bisect 라이브러리는 '정렬된 배열'에서 특정한 원소를 찾아야 할 때 매우 효과적으로 사용된다. bisect 라이브러리에서는 bisect_left() 함수와 bisect_right() 함수가 가장 중요하게 사용되며, 이 두 함수는 시간 복잡도 $O(logN)$ 에 동작한다.
- bisect_left(a, x) : 정렬된 순서를 유지하면서 리스트 a에 데이터 x를 삽입할 가장 왼쪽 인덱스를 찾는 메서드
- bisect_right(a, x) : 정렬된 순서를 유지하도록 리스트 a에 데이터 x를 삽입할 가장 오른쪽 인덱스를 찾는 메서드
예를 들어, 정렬된 리스트 [1, 2, 4, 4, 8]이 있을 때, 새롭게 데이터 4를 삽입하려 한다고 가정하자.
from bisect import bisect_left, bisect_right
a = [1, 2, 4, 4, 8]
x = 4
print(bisect_left(a, x)) # 2
print(bisect_right(a, x)) # 4
또한, bisect_left() 함수와 bisect_right() 함수는 '정렬된 리스트'에서 '값이 특정 범위에 속하는 원소의 개수'를 구하고자 할 때, 효과적으로 사용될 수 있다.
from bisect import bisect_left, bisect_right
# 값이 [left_value, right_value] 인 데이터의 개수를 반환하는 함수
def count_by_range(data, left_value, right_value):
left_idx = bisect_left(data, left_value)
right_idx = bisect_right(data, right_value)
# print("left_idx: ", left_idx, ", right_idx: ", right_idx)
return right_idx - left_idx
# 리스트 선언
data = [1, 2, 3, 3, 3, 3, 4, 4, 8, 9]
# 값이 4인 데이터 개수 출력
print(count_by_range(data, 4, 4)) # 2
# 값이 [-1, 3] 범위에 있는 데이터 개수 출력
print(count_by_range(data, -1, 3))
다시 말해 원소의 값을 x 라고 할 때, left_value <= x <= right_value 인 원소의 개수를 $O(logN)$ 으로 빠르게 계산할 수 있다.
collections
파이썬의 collections 라이브러리는 유용한 자료구조를 제공하는 표준 라이브러리다. collections 라이브러리의 기능 중에서 deque와 Counter에 대해 알아보자.
deque
리스트 자료형은 '가장 뒤쪽 원소'를 기준으로 삽입 또는 삭제가 수행되므로, 앞쪽에 있는 원소를 처리할 때에는 리스트에 포함된 데이터의 개수에 따라서 많은 시간이 소요될 수 있다.
리스트 | deque | |
가장 앞쪽에 원소 추가 | $O(N)$ | $O(1)$ |
가장 뒤쪽에 원소 추가 | $O(1)$ | $O(1)$ |
가장 앞쪽에 있는 원소 제거 | $O(N)$ | $O(1)$ |
가장 뒤쪽에 있는 원소 제거 | $O(1)$ | $O(1)$ |
deque에서는 리스트 자료형과 다르게 인덱싱, 슬라이싱 등의 기능은 사용할 수 없다. 다만, 연속적으로 나열된 데이터의 시작 부분이나 끝 부분에 데이터를 삽입하거나 삭제할 때는 매우 효과적으로 사용될 수 있다. deque는 스택이나 큐의 기능을 모두 포함한다고도 볼 수 있기 때문에 스택 혹은 큐 자료구조의 대용으로 사용될 수 있다.
deque는 첫 번째 원소를 제거할 때 popleft()를 사용하며, 마지막 원소를 제거할 때 pop()을 사용한다. 또한 첫 번째 인덱스에 원소 x를 삽입할 때 appendleft(x)를 사용하며, 마지막 인덱스에 원소를 삽입할 때 append(x)를 사용한다.
from collections import deque
data = deque([2, 3, 4])
data.appendleft(1)
data.append(5)
print(data)
print(list(data))
# 출력
# deque([1, 2, 3, 4, 5])
# [1, 2, 3, 4, 5]
Counter
파이썬 collections 라이브러리의 Counter는 등장 횟수를 세는 기능을 제공한다. 구체적으로 리스트와 같은 iterable 객체가 주어졌을 때, 해당 객체 내부의 원소가 몇 번씩 등작했는지를 알려준다. 따라서 원소별 등장 횟수를 세는 기능이 필요할 때 짧은 소스코드로 이를 구현할 수 있다.
from collections import Counter
counter = Counter(['red', 'blue', 'red', 'green', 'blue', 'blue'])
print(counter['blue'])
print(counter['green'])
print(dict(counter))
# 출력
# 3
# 1
# {'red': 2, 'blue': 3, 'green': 1}
math
math 라이브러리는 자주 사용되는 수학적인 기능을 포함하고 있는 라이브러리이다. 팩토리얼, 제곱근, 최대공약수(GCD) 등을 계산해주는 기능을 포함하고 있으므로, 수학 계산을 요구하는 문제를 만났을 때 효과적으로 사용될 수 있다.
import math
# 팩토리얼
print(math.factorial(5))
# 120
# 제곱근
print(math.sqrt(7))
# 2.6457513110645907
# 최대공약수
# gcd(a, b) -> a와 b의 최대 공약수를 반환
print(math.gcd(21, 14))
# 7
# 파이
print(math.pi) # 파이(pi) 출력
print(math.e) # 자연상수 e 출력
# 3.141592653589793
# 2.718281828459045
참고)
코딩교육 티씨피스쿨
4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등
tcpschool.com
최대공약수 (Greatest Common Divisor, GCD)
최소공배수(Lowest Common Multiple, LCM)