Python 자료구조와 함수
Python 자료구조와 함수
개요
파이썬의 핵심 자료구조 4종과 내장 함수, 슬라이싱, 고활용 함수, 주의사항까지 한 번에 정리한 레퍼런스 포스트.
1. 자료구조 개요
| 자료구조 | 순서 | 중복 | 변경 | 리터럴 표기 |
|---|---|---|---|---|
list | O | O | O | [1, 2, 3] |
tuple | O | O | X | (1, 2, 3) |
dict | O (3.7+) | 키 X / 값 O | O | {"a": 1} |
set | X | X | O | {1, 2, 3} |
1
2
3
4
5
6
7
8
9
10
11
** 자료구조 형식
set :
s1 = set([1, 2, 3, 4, 5, 6])
s2 = set([4, 5, 6, 7, 8, 9])
[300,20] : list
{300:20} : dict
(300, 20) :tuple
2. List (리스트)
특징
- 순서 있음, 중복 허용, 가변(mutable)
- 인덱싱 · 슬라이싱 모두 지원
- 어떤 타입이든 혼합 저장 가능
생성
1
2
3
a = [1, 2, 3]
b = list(range(5)) # [0, 1, 2, 3, 4]
c = [0] * 5 # [0, 0, 0, 0, 0]
기본 메서드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
a = [3, 1, 2]
a.append(4) # 끝에 추가 → [3, 1, 2, 4]
a.insert(1, 99) # 인덱스 1에 삽입 → [3, 99, 1, 2, 4]
a.extend([5, 6]) # 이터러블 이어붙이기 → [..., 5, 6]
a.remove(99) # 값으로 첫 번째 삭제
a.pop() # 마지막 요소 꺼내기 (반환 O)
a.pop(0) # 인덱스 0 꺼내기
a.sort() # 제자리 정렬 (반환 None)
a.reverse() # 제자리 뒤집기
a.index(2) # 값의 인덱스 반환
a.count(2) # 값의 개수 반환
a.clear() # 전체 비우기
a.copy() # 얕은 복사
슬라이싱 (List / Tuple / String 공통)
1
seq[start:stop:step]
start생략 → 처음부터stop생략 → 끝까지step음수 → 역방향
1
2
3
4
5
6
7
8
9
a = [0, 1, 2, 3, 4, 5]
a[1:4] # [1, 2, 3]
a[:3] # [0, 1, 2]
a[3:] # [3, 4, 5]
a[::2] # [0, 2, 4]
a[::-1] # [5, 4, 3, 2, 1] ← 전체 뒤집기
a[-3:] # [3, 4, 5] ← 뒤에서 3개
a[1:5:2] # [1, 3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
my_list = ["가", "나", "다", "라"]
a = my_list
# ①
print(my_list[-3:-4:-1])
# 출력: ['나']
# ②
print(my_list[0:-4:-1])
# 출력: []
# ③
print(a[3:-1:-1])
# 출력: []
# ④
print(a[3:2:-1])
# 출력: ['라']
# ⑤
print(a[3:0:-1])
# 출력: ['라', '다', '나']
# ⑥
print(a[-3::])
# 출력: ['나', '다', '라']
a[::-1]은 리스트를 새 객체로 뒤집어 반환하고,a.reverse()는 제자리에서 뒤집는다.
리스트 컴프리헨션
1
2
3
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
matrix = [[i*j for j in range(3)] for i in range(3)]
3. Tuple (튜플)
특징
- 순서 있음, 중복 허용, 불변(immutable)
- 생성 후 요소 수정 · 추가 · 삭제 불가
- 딕셔너리 키로 사용 가능 (hashable)
- 소괄호 없이 쉼표만으로도 생성됨
1
2
3
t = (1, 2, 3)
t2 = 1, 2, 3 # 괄호 없이도 튜플
single = (1,) # 요소 1개: 반드시 쉼표 필요 ← 주의
사용 가능 메서드
1
2
3
t = (3, 1, 2, 1)
t.index(1) # 1 (첫 번째 위치)
t.count(1) # 2 (개수)
언패킹
1
2
a, b, c = (1, 2, 3)
first, *rest = (1, 2, 3, 4) # first=1, rest=[2,3,4]
주요 활용
1
2
3
4
5
6
7
8
# 함수 다중 반환값
def minmax(lst):
return min(lst), max(lst)
lo, hi = minmax([3, 1, 5])
# 좌표, 구간 등 불변 쌍 표현
point = (37.5, 127.0)
4. Dictionary (딕셔너리)
특징
- 키-값(key-value) 쌍 저장
- Python 3.7+부터 삽입 순서 보장
- 키: 불변 타입만 가능 (str, int, tuple 등)
- 값: 모든 타입 가능
생성
1
2
3
d = {"name": "ram", "age": 25}
d2 = dict(name="ram", age=25)
d3 = dict.fromkeys(["a", "b", "c"], 0) # {"a":0, "b":0, "c":0}
기본 메서드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
d = {"a": 1, "b": 2, "c": 3}
d["a"] # 1 (없으면 KeyError)
d.get("z", 0) # 0 (없으면 기본값 반환, KeyError 없음)
d["d"] = 4 # 추가
del d["a"] # 삭제
d.pop("b") # 꺼내기 (반환 O)
d.update({"e": 5, "f": 6}) # 병합/업데이트
d.keys() # dict_keys 뷰
d.values() # dict_values 뷰
d.items() # dict_items 뷰 → (key, value) 튜플 이터러블
d.setdefault("g", 0) # 키 없으면 추가, 있으면 기존값 반환
d.clear() # 전체 비우기
d.copy() # 얕은 복사
딕셔너리 컴프리헨션
1
2
3
sq = {x: x**2 for x in range(5)} # {0:0, 1:1, 2:4, ...}
inv = {v: k for k, v in sq.items()} # 키-값 뒤집기
filtered = {k: v for k, v in d.items() if v > 1}
딕셔너리 병합 (Python 3.9+)
1
2
merged = d1 | d2 # 새 딕셔너리
d1 |= d2 # d1 제자리 업데이트
5. Set (집합)
특징
- 중복 없음, 순서 없음
- 빠른 멤버십 테스트 (
in) - 가변(mutable) →
frozenset으로 불변 버전 생성 가능
생성
1
2
3
s = {1, 2, 3}
s2 = set([1, 2, 2, 3]) # {1, 2, 3} ← 중복 제거됨
empty = set() # {}는 빈 dict이므로 반드시 set() 사용
기본 메서드
1
2
3
4
5
6
7
8
s = {1, 2, 3}
s.add(4) # 요소 추가
s.remove(2) # 없으면 KeyError
s.discard(99) # 없어도 에러 없음
s.pop() # 임의 요소 꺼내기
s.clear()
s.copy()
집합 연산
1
2
3
4
5
6
7
8
9
10
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
a | b # 합집합 {1,2,3,4,5,6} a.union(b)
a & b # 교집합 {3,4} a.intersection(b)
a - b # 차집합 {1,2} a.difference(b)
a ^ b # 대칭차 {1,2,5,6} a.symmetric_difference(b)
a <= b # a가 b의 부분집합? a.issubset(b)
a >= b # a가 b의 상위집합? a.issuperset(b)
6. 파이썬 내장 함수 (Built-in Functions)
자주 쓰는 기본 함수
1
2
3
4
5
6
7
len(obj) # 길이
type(obj) # 타입 반환
print(*args) # 출력
input(prompt) # 입력 (항상 str 반환)
range(stop) # range(start, stop, step)
id(obj) # 메모리 주소
isinstance(obj, T) # 타입 확인
수치 관련
1
2
3
4
5
6
7
abs(-3) # 3
round(3.567, 2) # 3.57
divmod(10, 3) # (3, 1) → 몫, 나머지 동시 반환
pow(2, 10) # 1024 (pow(2, 10, 1000) → 나머지)
max(iterable) # 최대값
min(iterable) # 최소값
sum(iterable, start=0)
타입 변환
1
2
3
4
5
6
7
8
int("42")
float("3.14")
str(42)
bool(0) # False
list((1,2,3))
tuple([1,2,3])
set([1,1,2])
dict(a=1)
이터러블 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# enumerate: 인덱스와 값을 동시에
for i, v in enumerate(["a","b","c"], start=1):
print(i, v)
# zip: 여러 이터러블을 묶음
for a, b in zip([1,2,3], ["x","y","z"]):
print(a, b)
# zip 주의: 짧은 쪽 기준으로 잘림
# itertools.zip_longest 사용 시 긴 쪽 기준
# map: 각 요소에 함수 적용 (lazy)
list(map(int, ["1","2","3"])) # [1,2,3]
list(map(lambda x: x**2, range(5)))
# filter: 조건에 맞는 요소만
list(filter(lambda x: x%2==0, range(10)))
# sorted: 새 리스트 반환
sorted([3,1,2]) # [1,2,3]
sorted([3,1,2], reverse=True) # [3,2,1]
sorted(words, key=len) # 길이 기준
sorted(lst, key=lambda x: x[1]) # 두 번째 요소 기준
# reversed: 역순 이터레이터
list(reversed([1,2,3])) # [3,2,1]
# any / all
any([False, True, False]) # True
all([True, True, True]) # True
# zip을 이용한 행렬 전치
matrix = [[1,2,3],[4,5,6]]
transposed = list(zip(*matrix)) # [(1,4),(2,5),(3,6)]
7. String 주요 메서드
문자열도 시퀀스이므로 슬라이싱, len, in 등 공통 연산 적용 가능.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
s = " Hello, Python! "
s.strip() # "Hello, Python!" 양쪽 공백 제거
s.lstrip() # 왼쪽만
s.rstrip() # 오른쪽만
s.lower() # " hello, python! "
s.upper()
s.title() # " Hello, Python! "
s.replace("Python", "World")
s.split(", ") # [" Hello", "Python! "]
" ".join(["a","b","c"]) # "a b c"
s.find("Python") # 인덱스 반환 (-1 if not found)
s.index("Python") # 인덱스 반환 (없으면 ValueError)
s.startswith(" H")
s.endswith("! ")
s.count("l") # 개수
s.zfill(20) # 왼쪽 0 채우기
s.center(30, "-") # 가운데 정렬
"42".isnumeric() # True
"abc".isalpha() # True
s.strip().isdigit()
# f-string (3.6+)
name, score = "람", 99
f"{name}의 점수: {score:.2f}"
# format
"{0} + {1} = {2}".format(1, 2, 3)
8. 활용도 높은 고급 함수 / 모듈
collections
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from collections import Counter, defaultdict, deque, OrderedDict
# Counter: 빈도 계산
c = Counter("abracadabra")
c.most_common(2) # [('a',5),('b',2)]
# defaultdict: 키 없을 때 기본값 자동 생성
dd = defaultdict(list)
dd["key"].append(1) # KeyError 없음
# deque: 양방향 큐 (O(1) appendleft/popleft)
dq = deque([1,2,3])
dq.appendleft(0)
dq.popleft()
dq.rotate(1) # 오른쪽으로 1 회전
itertools
1
2
3
4
5
6
7
from itertools import chain, product, combinations, permutations, accumulate
list(chain([1,2],[3,4])) # [1,2,3,4]
list(product([1,2],[3,4])) # 데카르트 곱
list(combinations([1,2,3], 2)) # 조합
list(permutations([1,2,3], 2)) # 순열
list(accumulate([1,2,3,4])) # 누적합 [1,3,6,10]
functools
1
2
3
4
5
6
7
8
9
from functools import reduce, lru_cache, partial
reduce(lambda a, b: a+b, [1,2,3,4]) # 10
@lru_cache(maxsize=None)
def fib(n):
return n if n < 2 else fib(n-1) + fib(n-2)
double = partial(pow, exp=2) # 인자 고정
heapq (최소 힙)
1
2
3
4
5
6
7
8
import heapq
h = [3,1,4,1,5]
heapq.heapify(h) # 제자리 힙 변환
heapq.heappush(h, 2)
heapq.heappop(h) # 최솟값 반환
heapq.nlargest(3, h) # 상위 3개
heapq.nsmallest(3, h) # 하위 3개
9. 주의해야 할 부분
① 얕은 복사 vs 깊은 복사
1
2
3
4
5
6
7
8
import copy
a = [[1,2],[3,4]]
b = a.copy() # 얕은 복사: 내부 리스트는 참조 공유
b[0].append(99)
print(a) # [[1, 2, 99], [3, 4]] ← a도 변경됨!
c = copy.deepcopy(a) # 깊은 복사: 완전히 독립
② 리스트 곱셈의 함정
1
2
3
4
5
6
7
8
9
10
# 1차원: 문제없음
a = [0] * 5 # [0, 0, 0, 0, 0]
# 2차원: 모든 행이 같은 객체!
matrix = [[0] * 3] * 3
matrix[0][0] = 1
print(matrix) # [[1,0,0],[1,0,0],[1,0,0]] ← 함정!
# 올바른 방법
matrix = [[0] * 3 for _ in range(3)]
③ 단일 요소 튜플
1
2
t = (1) # int → 괄호는 연산자
t = (1,) # tuple → 반드시 쉼표 필요
④ 빈 set 생성
1
2
s = {} # dict ← 주의!
s = set() # set
⑤ sort() vs sorted()
1
2
3
4
5
a = [3,1,2]
sorted(a) # 새 리스트 반환, a 변경 없음
a.sort() # 제자리 정렬, None 반환
result = a.sort() # result는 None!
⑥ dict.get() 활용
1
2
3
d = {"a": 1}
d["z"] # KeyError!
d.get("z", 0) # 0 ← 안전한 접근
⑦ 가변 기본 인수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 잘못된 패턴: 기본 인수가 함수 정의 시 한 번만 생성됨
def add(item, lst=[]):
lst.append(item)
return lst
add(1) # [1]
add(2) # [1, 2] ← 의도치 않게 공유됨!
# 올바른 패턴
def add(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
⑧ map / filter는 이터레이터
1
2
3
4
result = map(str, [1,2,3])
print(result) # <map object>
print(list(result)) # ['1','2','3']
print(list(result)) # [] ← 한 번 소진되면 비어있음!
⑨ set는 순서 보장 없음
1
2
3
s = {3, 1, 2}
list(s) # [1, 2, 3] 또는 다른 순서 — 보장 없음
# 순서가 필요하면 sorted(s) 사용
⑩ 문자열 불변성
1
2
3
s = "hello"
s[0] = "H" # TypeError: str은 immutable!
s = "H" + s[1:] # 새 문자열 생성
10. 한눈에 보는 시간 복잡도
| 연산 | list | dict | set |
|---|---|---|---|
| 인덱스 접근 | O(1) | - | - |
in 검색 | O(n) | O(1) | O(1) |
| 추가 (끝) | O(1) | O(1) | O(1) |
| 삽입 (중간) | O(n) | - | - |
| 삭제 (끝) | O(1) | O(1) | O(1) |
| 삭제 (중간) | O(n) | - | - |
멤버십 검색이 빈번하면
list대신set또는dict를 사용할 것.
참고
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.