python은 1991년 귀도 반 로섬(Guido van Rossum)이라는 프로그래머에 의해 개발된 언어로
다양한 라이브러리를 통해 높은 생산성을 가진 언어이다. 본 포스팅에서는 python에서 사용하는 기본적인 라이브러리와 이를 사용하는 방법을 정리함으로써 python을 좀 더 손쉽게 사용할 수 있는 방법을 제시하고자 한다.
내장함수 : print(), input()과 같은 기본 입출력 기능부터 sorted()와 같은 정렬 기능을 포함하고 있는 기본 내장 라이브러리
itertools : 파이썬에서 반복되는 형태의 데이터를 처리하는 기능을 제공하는 라이브러리, 순열과 조합 라이브러리를 제공
heapq : 힙(Heap) 기능을 제공하는 라이브러리. 우선순위 큐 기능을 구현하기 위해 사용한다.
collections : 덱(deque), 카운터(Counter) 등의 유용한 자료구조를 포함하고 있는 라이브러리이다.
math : 필수적인 수학적 기능을 제공하는 라이브러리이다. 팩토리얼, 제곱근, 최대공약수, 삼각함수 관련 메서드부터 파이(pi)와 같은 상수를 포함하고 있다
bisect : 이진탐색을 위한 라이브러리
functools: 누적집계를 위한 reduce() 함수 사용 가능
for i, letter in enumerate(['A', 'B', 'C']):
print(i, letter)
# 0 A
# 1 B
# 2 C
for i, letter in enumerate(['A', 'B', 'C'], start=1):
print(i, letter)
# 1 A
# 2 B
# 3 C
a = 1e9 // 1,000,000,000
a = 75.25e1 // 752.5
a = 3954e-3 // 3.954
round(123.456, 2) // 123.46
# 길이가 정해진 리스트 만들기
array = [0 for i in range(n)]
# 0부터 19까지의 수 중에서 홀수만 포함하는 리스트
array = [ i for i in range(20) if i % 2 == 1 ]
# 1부터 9까지의 수의 제곱 값을 포함하는 리스트
array = [ i**2 for i in range(10) ]
# 2차원 리스트 초기화
n = 3
m = 3
array = [[0] * m for _ in range(n)]
print(array)
변수.reverse() # 리스트의 순서 모두 뒤집음
변수.count(특정 값) # 리스트에서 특정 값을 가지는 데이터의 개수
변수.remove(특정 값) # 특정 값 가지는 원소 제거, 값이 여러 개면 하나만 제거
append() 함수는 O(1)에 실행되지만
insert() 함수는 O(N)에 실행된다 # 원소를 삽입한 뒤에, 리스트의 원소 위치를 조정해줘야 하기 때문
특정한 값의 원소를 모두 제거하려면?
a = [1, 2, 3, 4, 5]
remove_set = [1, 4]
result = [i for i in a if i not in remove_set] // [2, 3, 5]
#list Null Check?
if not list1:
print("list1 is empty")
a = "Hello"
b = "World"
print(a+b)
print(a + " " + b)
#튜플 자료형은 리스트와 거의 비슷하지만 다음과 같은 차이가 있다.
-튜플은 한 번 선언된 값을 변경할 수 없다.
-리스트는 대괄호를([])를 이용하지만, 튜플은 소괄호(())를 이용한다
튜플 자료형은 그래프 알고리즘을 구현할 때 자주 사용된다.
data = dict()
data['사과'] = 'apple'
data['바나나'] = 'banana'
data['코코넛'] = 'coconut'
# 키 데이터만 담은 리스트
key_list = data.keys()
# 값 데이터만 담은 리스트
value_list = data.values()
# 각 기에 따른 값을 하나씩 출력
for key in key_list:
print(data[key])
# Set은 다음과 같은 특징이 있다.
-중복을 허용하지 않는다.
-순서가 없다.
# Set 초기화 방법 1
data = set([1, 1, 2, 3, 4, 4, 5])
# Set 초기화 방법 2
data = {1, 1, 2, 3, 4, 4, 5}
# Set의 연산
a = set([1, 2, 3, 4, 5])
b = set([3, 4, 5, 6, 7])
print(a | b) # 합집합
print(a & b) # 교집합
print(a - b) # 차집합
{1, 2, 3, 4, 5, 6, 7}{3, 4, 5}{1, 2}
Set 관련 함수
# 하나의 원소을 추가할 때는 add()
data.add(4)
# 여러 개의 원소를 추가할 때는 update()
data.update([5, 6])
# 특정한 값을 갖는 원소 삭제
data.remove(3)
입력의 개수가 많은 경우에는 input() 함수를 그대로 사용하지는 않는다.
파이썬의 기본 input() 함수는 동작 속도가 느려서 시간 초과로 오답 판정을 받을 수 있기 때문
이 경우 파이썬의 sys 라이브러리에 정의되어 있는 sys.stdin.readline() 함수를 이용한다.
다음과 같은 방식으로 사용하며 input() 함수와 같이 한 줄씩 입력받기 위함
import sys
sys.stdin.readline().rstrip()
sys 라이브러리를 사용할 때는 한 줄 입력을 받고 나서 rstrip() 함수를 꼭 호출해야 한다.
문자열과 수를 함께 출력해야 되는 경우 단순히 + 연산자를 이용하여 문자열과 수를 더하면 오류가 발생한다.
# 오류 발생 코드
answer = 7
print("정답은 " + answer + "입니다.")
# 해결법
-str() 함수를 이용하여 출력하고자 하는 변수 데이터를 문자열로 바꾸어줌
-각 자료형을 콤마(,)를 기준으로 구분하여 출력
# f
-파이썬 3.6 이상의 버전부터 f-string 문법 사용 가능
-f-string은 문자열 앞에 접두사 'f'를 붙임으로써 사용할 수 있다
print(f"정답은 {answer}입니다")
# 리스트와 같은 iterable 객체에서 r개의 데이터를 뽑아 일렬로 나열하는 모든 경우(순열)을 계산해준다.
# permutations는 클래스이므로 객체 초기화 이후에는 리스트 자료형으로 변환하여 사용한다.
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', 'B', 'A')]
# combinations는 리스트와 같은 iterable 객체에서 r개의 데이터를 뽑아 순서를 고려하지 않고 나열하는 모든 경우(조합)을 계산한다.
# combinations는 클래스이므로 객체 초기화 이후에는 리스트 자료형으로 변환하여 사용한다.
from itertools import combinations
data = ['A', 'B', 'C']
result = list(combinations(data, 2)) # 2개를 뽑는 모든 조합 구하기
print(result)
[('A', 'B'), ('A', 'C'), ('B', 'C')]
# product는 permutations와 같이 리스트와 같은 iterable 객체에서 r개의 데이터를 뽑아
일렬로 나열하는 모든 경우(순열)를 계산한다. 다만 원소를 중복하여 뽑는다 <- 중요!
# product 객체를 초가화 할 때는 데이터의 수를 repeat 속성값으로 넣어준다.
# product는 클래스이므로 객체 초기화 이후에는 리스트 자료형으로 변환하여 사용한다.
from itertools import product
data = [1, 2, 3]
result = list(product(data, repeat=2)) # 2개를 뽑는 모든 순열 구하기(중복 허용)
print(result)
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
# combination_with_replacement는 combinations와 같이 리스트와 같은 iterable 객체에서
r개의 데이터를 뽑아 순서를 고려하지 않고 나열하는 모든 경우(조합)을 계산한다.
# 다만 원소를 중복해서 뽑는다.
# combination_with_replacement는 클래스이므로 객체 초기화 이후에는 리스트 자료형으로 변환하여 사용한다.
from itertools import combinations_with_replacement
data = [1, 2, 3]
result = list(combinations_with_replacement(data, 2)) # 2개를 뽑는 모든 조합 구하기(중복 허용)
print(result)
[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
permutations # 모든 순열 구하기
combinations # 2개를 뽑는 모든 조합 구하기
product # 2개를 뽑는 모든 순열 구하기(중복 허용)
combination_with_replacement # 2개를 뽑는 모든 조합 구하기(중복 허용)
# 파이썬의 힙은 최소 힙으로 구성되어 있으므로 단순히 원소를 힙에 전부 넣었다가 빼는 것만으로도
시간 복잡도 O(NlogN)에 오름차순 정렬이 완료된다
# heapq.heappush() // 힙에 원소 삽입
# heapq.heappop() // 힙에서 원소 꺼냄
# heapq.heapify() // list를 heapq로 변환
# 파이썬에서는 최대 힙을 제공하지 않는다. 따라서 heapq 라이브러리를 이용하여 최대 힙을 구현해야 할 때는
원소의 부호를 임시로 변경하는 방식을 사용한다. 삽입 전에 부호를 반대로 바꾸었다가, 꺼낸 뒤에 다시 원소의 부호를 바꾸면 된다.
import heapq
def heapsort(iterable):
h = []
result = []
for value in iterable:
heapq.heappush(h, -value)
for _ 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)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# 파이썬에서는 이진 탐색을 쉽게 구현할 수 있도록 bisect 라이브러리를 제공한다.
# bisect 라이브러리는 '정렬된 배열'에서 특정한 원소를 찾아야 할 때 매우 효과적으로 사용된다.
# 이 두 메서드는 시간 복잡도 O(logN)에 동작한다.
bisect_left(a, x) #정렬된 순서를 유지하면서 리스트 a에 데이터 x를 삽입할 가장 왼쪽 인덱스를 찾는 메서드
bisect_right(a, x) #정렬된 순서를 유지하도록 리스트 a에 데이터 x를 삽입할 가장 오른쪽 인덱스를 찾는 메서드
# 예를 들어 정렬된 리스트 [1, 2, 4, 4, 8]이 있을 때, 새롭게 데이터 4를 삽입하려 한다.
list = [1, 2, 4, 4, 8]
bisect_left(list, 4) # 2 반환
bisect_right(list, 4) # 4 반환
# Binary Search
while l <= r:
mid = (l+r) // 2
if nums[mid] >= n:
result = mid
r = mid - 1
else: l = mid + 1
# 배열이 오름차순으로 정렬된 점을 이용해서, mid를 집고, mid 인덱스의 값이 작으면 l(left) 을 mid +1 로 올려 다음 후보 값을 높여주고, 아니면 r(right)을 mid -1 로 내려 다음 후보 값을 낮춰주는 방식입니다. 절반씩 후보를 줄여가기에 O(logN) 이 성립합니다.
/* Function */
def binary_search(arr, target):
low, high = 0, len(arr) - 1
while low <= high:
mid = (low + high) // 2
if arr[mid] > target:
high = mid - 1
if arr[mid] == target:
return mid
if arr[mid] < target:
low = mid + 1
return -1
# 보통 파이썬에서는 deque를 이용해 큐를 구현
# 리스트 자료형에서 앞쪽에 있는 원소를 삭제하거나 앞쪽에 새 원소를 삽입할 때의 시간복잡도는 O(N)이다.
하지만 deque의 경우 O(1)
# deque에서는 리스트와 다르게 인덱싱, 슬라이싱 등의 기능을 사용할 수 없다.
다만 연속적으로 나열된 데이터의 시작 부분이나 끝부분에 데이터를 삽입하거나 삭제할 때는 매우 효과적으로 사용될 수 있다
# deque는 스택이나 큐의 대용으로 사용될 수 있다.
popleft() # 첫 번째 원소 제거
pop() # 마지막 원소 제거
appendleft() # 첫 번째 인덱스에 원소 삽입
append() # 마지막 인덱스에 원소 삽입
# 따라서 deque를 queue로 이용할 때, 원소를 삽입할 때는 append()를 사용하고 삭제할 때에는 popleft()를 사용하면 된다.
def countLetters(word):
counter = {}
for letter in word:
if letter not in counter:
counter[letter] = 0
counter[letter] += 1
return counter
countLetters('hello world'))
# {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}
# Counter는 등장 횟수를 세는 기능을 제공한다.
from collections import Counter
Counter('hello world')
# Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
def find_max(word):
counter = Counter(word)
max_count = -1
for letter in counter:
if counter[letter] > max_count:
max_count = counter[letter]
max_letter = letter
return max_letter, max_count
find_max('hello world') # ('l', 3)
# 데이터의 개수가 많은 순으로 정렬된 배열을 리턴
Counter('hello world').most_common() # [('l', 3), ('o', 2), ('h', 1), ('e', 1), (' ', 1), ('w', 1), ('r', 1), ('d', 1)]
Counter('hello world').most_common(1) # [('l', 3)]
import math
print(math.factorial(5)) # 5! 출력
print(math.sqrt(7) # 루트7 출력
print(math.gcd(21, 14)) # 21과 14의 최대 공약수 출력
print(math.lcm(21, 14)) # 21과 14의 최소 공배수 출력
print(math.pi) # 파이(pi) 출력
print (math.e) # 자연상수 e 출력
입력 데이터의 개수가 많은 문제에 input() 함수를 사용하면 동작 속도가 느려서 시간 초과로 오답 판정을 받을 수 있다. 입력 데이터가 많은 문제는 sys 라이브러리의 readline() 함수를 이용하면 시간 초과를 피할 수 있다.
import sys
input_data = sys.stdin.readline().rstrip()
print(input_data)
sys 라이브러리를 사용할 때는 한 줄 입력받고 나서 꼭 rstrip()
함수를 호출해야 한다.readline()
으로 입력하면 입력 후 엔터가 줄 바꿈 기호로 입력되는데, 이 공백 문자를 제거하기 위해 사용.관행적으로 외워서 사용하자.
https://ko.wikipedia.org/wiki/%ED%8C%8C%EC%9D%B4%EC%8D%AC
https://velog.io/@eazyan/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-for-%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8