좋아! 이번엔 파이썬 실전 코딩과 정보처리기사 실기에서 아주 자주 등장하는 실용 문법인 9번 enumerate, zip 그리고 **10번 map, filter, reduce**에 대해
기초 개념 → 실전 예제 → 디버깅 식 흐름 해설로 줄줄이 완전 해부해줄게!
enumerate() & zip() — 반복문 마스터 키enumerate() — 인덱스 + 값 동시에arr = ['a', 'b', 'c']
for i, val in enumerate(arr):
print(i, val)
📌 결과:
0 a
1 b
2 c
✅ 해석:
enumerate(arr)는 (인덱스, 값) 형태로 묶어줌for문 돌 때 i엔 인덱스, val엔 값이 들어감기존 방법:
for i in range(len(arr)):
print(i, arr[i])
enumerate는 훨씬 깔끔하고 실수 줄어듦
for i, val in enumerate(['a', 'b'], start=1):
print(i, val)
# 1 a
# 2 b
zip() — 여러 리스트를 동시에 반복names = ['A', 'B', 'C']
scores = [90, 80, 70]
for name, score in zip(names, scores):
print(name, score)
📌 결과:
A 90
B 80
C 70
✅ 해석:
zip()은 여러 iterable을 짝지어서 하나의 튜플로 반환zipped = list(zip([1,2], [3,4]))
print(zipped) # [(1,3), (2,4)]
zipped = [('a', 1), ('b', 2)]
letters, numbers = zip(*zipped)
print(letters) # ('a', 'b')
print(numbers) # (1, 2)
enumerate & zip 요약| 함수 | 역할 | 주의 |
|---|---|---|
enumerate() | 인덱스와 값을 동시에 | for i, x in ... 구조 |
zip() | 여러 리스트 묶기 | 길이 짧은 쪽 기준으로 동작 |
map(), filter(), reduce() — 함수형 프로그래밍 도구map(function, iterable) — 변환nums = ['1', '2', '3']
nums_int = list(map(int, nums)) # [1, 2, 3]
📌 해석:
int()를 적용해서 리스트 반환squared = list(map(lambda x: x**2, [1, 2, 3]))
print(squared) # [1, 4, 9]
filter(function, iterable) — 조건 필터링even = list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4]))
print(even) # [2, 4]
📌 해석:
lambda의 조건을 만족하는 값만 남김reduce(function, iterable) — 누적 계산from functools import reduce
total = reduce(lambda x, y: x + y, [1, 2, 3, 4])
print(total) # 10
✅ 해석:
1 + 2 = 33 + 3 = 66 + 4 = 10s = "1 2 3"
arr = list(map(int, s.split()))
# [1, 2, 3]
→ 정보처리기사 실기에서 입력 처리 시 거의 필수
nums = [1, 2, 3, 4, 5]
doubled_evens = list(filter(lambda x: x % 2 == 0, map(lambda x: x*2, nums)))
print(doubled_evens) # [4, 8]
| 함수 | 기능 | 예시 결과 |
|---|---|---|
enumerate() | 인덱스 + 값 | (0, 'a'), (1, 'b') |
zip() | 여러 리스트 묶기 | (a, 90), (b, 80) |
map(f, iter) | 각 요소 변환 | [f(x1), f(x2), ...] |
filter(f, iter) | 조건 통과 요소만 | [x for x if f(x)] |
reduce(f, iter) | 누적 계산 | f(f(f(x1,x2),x3),x4) |
아주 좋은 질문이야!
바로 그 **** 연산자는 파이썬에서 "거듭제곱(제곱, 제곱근 등)"을 나타내는 연산자야.
** 연산자: 거듭제곱 (Exponentiation)x ** y
는 x의 y제곱, 즉 "x를 y번 곱한 것"을 의미해.
print(2 ** 3) # 2 * 2 * 2 = 8
print(5 ** 2) # 5 * 5 = 25
print(9 ** 0.5) # 9의 제곱근 = 3.0
📌 결과:
8
25
3.0
| 코드 | 의미 | 계산 결과 |
|---|---|---|
2 ** 3 | 2의 3제곱 | 8 |
3 ** 2 | 3의 2제곱 | 9 |
9 ** 0.5 | 9의 제곱근 (½ 제곱) | 3.0 |
16 ** 0.25 | 4제곱근 | 2.0 |
squared = list(map(lambda x: x**2, [1, 2, 3]))
이 코드는 다음과 같이 동작해:
map(lambda x: x**2, [1, 2, 3])
→ 각각 x=1, x=2, x=3에 대해
→ x**2 즉 1**2=1, 2**2=4, 3**2=9
그 결과가 [1, 4, 9]이 되고
list()로 묶어서 리스트로 반환
| x | x**2 |
|---|---|
| 1 | 1 |
| 2 | 4 |
| 3 | 9 |
**는 왜 쓰일까?| 표현 | 의미 |
|---|---|
x ** 0.5 | 제곱근 |
x ** 2 | 제곱 |
x ** 3 | 세제곱 |
x ** -1 | 역수 (1/x) |
| 기호 | 의미 | 예시 |
|---|---|---|
** | 거듭제곱 | 2 ** 3 = 8, 9 ** 0.5 = 3.0 |
좋아! 너가 말한 ** 연산자는 두 가지 전혀 다른 쓰임이 있어서, 이걸 잘 구분하는 게 실전에서 실수를 막는 핵심 포인트야.
** 두 가지 용도 정리| 형태 | 의미 | 예시 |
|---|---|---|
x ** y | 거듭제곱 연산자 | 2 ** 3 = 8 |
**kwargs / **딕셔너리 | 딕셔너리 언팩/가변 인자 | def f(**kwargs) / f(**d) |
** = 거듭제곱 (앞에서 설명한 내용)print(2 ** 3) # 8
print(9 ** 0.5) # 3.0
**kwargs: 키워드 인자 받을 때 사용def greet(**kwargs):
for key, value in kwargs.items():
print(f"{key} = {value}")
greet(name="Hansun", age=25)
📌 결과:
name = Hansun
age = 25
✅ 해석:
**kwargs는 키워드 인자를 딕셔너리 형태로 묶어서 받는다kwargs = {"name": "Hansun", "age": 25} 처럼 처리됨**dict = 딕셔너리 언팩(풀기)def add(a, b):
return a + b
params = {'a': 3, 'b': 5}
print(add(**params)) # 8
📌 해석:
add(**params)는 → add(a=3, b=5)처럼 호출됨**는 딕셔너리 params를 키-값으로 분해해서 함수에 넘김# 호출 예시
def f(a, b): ...
params = {'a': 1, 'b': 2}
f(**params) ← f(a=1, b=2)
| 쓰임 | 예시 | 의미 |
|---|---|---|
| 거듭제곱 | x ** y | x의 y 제곱 |
| 키워드 인자 받기 | def f(**kwargs) | 키워드 인자를 dict로 받음 |
| 딕셔너리 언팩 | f(**dict) | dict를 분해해서 인자로 넘김 |
| 실수 유형 | 올바른 형태 |
|---|---|
**(a, b) ❌ | **{'a': 1, 'b': 2} ✅ |
f(1, 2, 3)에 **args 사용 ❌ | *args 사용해야 함 ✅ |
def profile(name, age):
print(f"{name} is {age} years old.")
info = {'name': 'Hansun', 'age': 25}
profile(**info) # 언팩 호출 → profile(name='Hansun', age=25)
좋아, 이제 정말 중요한 걸 하게 됐어.
많은 사람들이 헷갈리는
✅
*argsvs**kwargs
✅*와**연산자의 다른 쓰임 (언팩, 곱셈 등)
을 총정리 표 + 디버깅 예제 + 실전 용례로 완전 해부해줄게.
*args vs **kwargs: 함수에서 가변 인자 받기*args: 위치 인자 (positional arguments)def add_all(*args):
print(args)
add_all(1, 2, 3)
# 출력: (1, 2, 3)
🔍 해석:
*args는 인자들을 튜플로 받음 → (1, 2, 3)for x in args:처럼 순회 가능**kwargs: 키워드 인자 (keyword arguments)def show_info(**kwargs):
print(kwargs)
show_info(name="Hansun", age=25)
# 출력: {'name': 'Hansun', 'age': 25}
🔍 해석:
**kwargs는 인자들을 딕셔너리로 받음| 항목 | 예시 | 내부 구조 |
|---|---|---|
*args | f(1, 2, 3) | (1, 2, 3) (튜플) |
**kwargs | f(a=1, b=2) | {'a': 1, 'b': 2} (딕셔너리) |
* / ** 언팩 (반대로 풀기)*리스트 → 함수 위치 인자로 넘기기def add(a, b, c):
print(a + b + c)
args = [1, 2, 3]
add(*args) # == add(1, 2, 3)
**딕셔너리 → 함수 키워드 인자로 넘기기def intro(name, age):
print(f"{name} is {age} years old.")
params = {'name': 'Hansun', 'age': 25}
intro(**params) # == intro(name='Hansun', age=25)
def f(x, y, z):
print(x, y, z)
args = [10, 20, 30]
f(*args) # == f(10, 20, 30)
kwargs = {'x': 10, 'y': 20, 'z': 30}
f(**kwargs) # == f(x=10, y=20, z=30)
*와 ** 연산자의 "다른 쓰임"a = [1, 2]
b = [3, 4]
c = [*a, *b]
print(c) # [1, 2, 3, 4]
d1 = {'x': 1}
d2 = {'y': 2}
d = {**d1, **d2}
print(d) # {'x': 1, 'y': 2}
*print([0] * 3) # [0, 0, 0]
print("Hi" * 2) # "HiHi"
✅ 여기에선 단순한 반복 곱셈 연산자
| 문법 | 의미 | 예시 |
|---|---|---|
*args | 위치 인자 묶기 | def f(*args): → (1,2,3) |
**kwargs | 키워드 인자 묶기 | def f(**kwargs): → {'a':1} |
*리스트 | 리스트 언팩 (풀기) | f(*[1,2,3]) → f(1,2,3) |
**딕트 | 딕셔너리 언팩 | f(**{'x':1}) → f(x=1) |
[0]*3 | 반복 | [0, 0, 0] |
"a"*4 | 문자열 반복 | "aaaa" |
| 실수 예시 | 문제점 | 해결 방법 |
|---|---|---|
f(*{'a': 1}) | dict는 키만 언팩됨 → 에러 | f(**{'a': 1})로 해야 함 |
*args = (1,2,3) | 문법 에러 | 함수 인자에서만 사용 |
[0]*3]*4 | 얕은 복사 트랩 | [[0]*3 for _ in range(4)]로 |
*args, **kwargs 동시 사용 예제def all_info(*args, **kwargs):
print("Positional:", args)
print("Keyworded:", kwargs)
all_info(1, 2, name='Hansun', age=25)
📌 결과:
Positional: (1, 2)
Keyworded: {'name': 'Hansun', 'age': 25}
* : 위치 인자, 리스트 언팩, 반복, 곱셈** : 키워드 인자, 딕셔너리 언팩, 제곱*args, **kwargs는 함수 정의/호출에서 모두 중요dict와 *, **를 혼합한 문제 자주 나옴좋아! 지금부터 파이썬 실전 코딩에서 실수하면 터지는 트랩 11~13번, 즉
🔹 11. try-except 예외 처리
🔹 12. 자주 쓰이는 모듈들 (heapq, itertools, collections)
🔹 13. is와 ==의 차이 (비교 연산 트랩)
를 하나씩, 개념 → 실제 코드 흐름 → 왜 그렇게 되는가 형식으로 완전히 해부해서 알려줄게.
try / except — 예외 처리 구조try:
# 오류가 날 수 있는 코드
risky_code()
except SomeError:
# 예외 발생 시 실행할 코드
handle_it()
try:
x = 5 / 0
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
📌 결과:
0으로 나눌 수 없습니다.
try: 블록에서 예외가 발생하면ZeroDivisionError)에 맞는 except 블록으로 점프try:
num = int(input("숫자 입력: "))
print(10 / num)
except ValueError:
print("숫자를 입력하세요.")
except ZeroDivisionError:
print("0으로 나누지 마세요.")
| 요소 | 역할 |
|---|---|
try: | 예외 발생할 수 있는 코드 블록 |
except: | 예외 발생 시 실행할 코드 |
finally: | 예외 여부와 무관하게 항상 실행됨 (선택) |
heapq — 우선순위 큐 (최소 힙)import heapq
heap = []
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 5)
print(heapq.heappop(heap)) # 1 ← 가장 작은 값부터 나감
✅ 자동 정렬되는 큐!
→ 정보처리기사 실기에서 최단거리, 스케줄링 문제에 자주 등장
itertools — 반복자 도구들from itertools import permutations, combinations
print(list(permutations([1, 2], 2))) # [(1, 2), (2, 1)]
print(list(combinations([1, 2, 3], 2))) # [(1,2), (1,3), (2,3)]
✅ 순열, 조합, 중복 순열, 누적 합 등 다양한 반복자 제공
→ 경우의 수, 조합 탐색 문제에서 자주 사용됨
collections — 자료구조 단축버전 모음from collections import deque
q = deque([1, 2, 3])
q.appendleft(0)
q.append(4)
print(q) # deque([0, 1, 2, 3, 4])
from collections import defaultdict
d = defaultdict(int)
d['a'] += 1
print(d['a']) # 1
| 모듈 | 용도 | 핵심 함수 |
|---|---|---|
heapq | 우선순위 큐 | heappush, heappop |
itertools | 순열/조합 | permutations, combinations |
collections | 구조 | deque, defaultdict, Counter |
== vs is — 완전히 다르다!| 연산자 | 의미 |
|---|---|
== | 값이 같은가? |
is | 동일한 객체인가? (같은 메모리 주소?) |
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # True → 값이 같음
print(a is b) # False → 다른 객체 (주소 다름)
a = [1, 2]
b = a # 같은 객체 가리킴
print(a == b) # True
print(a is b) # True ← 이건 진짜 같은 메모리
x = 256
y = 256
print(x is y) # True (캐싱)
x = 257
y = 257
print(x is y) # False (캐싱 안 됨)
s1 = "hello"
s2 = "hello"
print(s1 is s2) # True
| 비교 | == | is |
|---|---|---|
| 의미 | 값 비교 | 객체(메모리) 비교 |
| 리스트 | True / False | False |
| 같은 변수 대입 | True | True |
| 숫자/문자열 | 상황에 따라 True (캐싱) | 자주 헷갈림 |
| 항목 | 설명 | 실전 예시 |
|---|---|---|
try-except | 예외 발생을 안전하게 처리 | try: 5/0 except: |
heapq | 최소값 빠른 접근 | heappush, heappop |
itertools | 조합, 순열 반복 | permutations |
collections | 자료구조 간편 버전 | deque, defaultdict |
== vs is | 값 vs 객체 비교 | a==b vs a is b |