포스트

Python 자료구조와 함수

Python 자료구조와 함수

개요

파이썬의 핵심 자료구조 4종과 내장 함수, 슬라이싱, 고활용 함수, 주의사항까지 한 번에 정리한 레퍼런스 포스트.


1. 자료구조 개요

자료구조순서중복변경리터럴 표기
listOOO[1, 2, 3]
tupleOOX(1, 2, 3)
dictO (3.7+)키 X / 값 OO{"a": 1}
setXXO{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. 한눈에 보는 시간 복잡도

연산listdictset
인덱스 접근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 라이센스를 따릅니다.