파이썬 기초 다지기

류한선·2025년 7월 5일

실기연습-2

목록 보기
88/95

너무 좋은 문제의식이야. 실전에서 겪는 혼란 대부분은 "기초 문법은 알지만 실전에선 못 쓰는 이유" 때문이야. 이제부터 그걸 정리해서 단계별로 어떻게 극복할 수 있는지 알려줄게. 특히 정보처리기사 실기 문제파이썬 코드 해석에 강해지기 위한 방향으로 설명해줄게.


✅ 1. 어디서 막히는가? (정확한 원인 파악)

너가 말한 걸 기반으로 하면 주로 아래 영역에서 막히는 거야:

분류예시어떤 착오?
고급 문법 등장*args, **kwargs, list comprehension, lambda, map/filter/reduce생소하거나 동작 순서를 모름
내장 자료구조 활용dict, set, deque, heapq, defaultdict, Counter생김새는 아는데 쓰는 이유를 모름
객체/포인터 개념list, dict가 복사되면 왜 원본도 바뀌는지얕은 복사 vs 깊은 복사 모름
알고리즘적 패턴정렬, 슬라이딩 윈도우, BFS/DFS, 백트래킹구현은 외웠는데 문제에선 못 떠올림
조건문/루프 흐름if not A or B, for i in range(n-1, -1, -1)조건 순서나 논리 흐름이 헷갈림

✅ 2. 어떻게 공부하면 되는가? (실전 강화 전략)

📌 전략 A: 실전 코드에서 튀어나온 문법을 “이해”하며 외우기

  • 코드 보다가 생소한 문법이 나오면 "이건 뭐지?" 하면서 따로 예제 코드를 만들어보고
  • print() 찍어가면서 디버깅 해보기
  • 한줄 한줄 설명식 해석해보기 (너가 원하는 스타일로 내가 도와줄게)

예시 1: lambda x: x[1]

arr = [(1, 3), (2, 2), (3, 1)]
arr.sort(key=lambda x: x[1])
print(arr)  # [(3, 1), (2, 2), (1, 3)]

생긴 건 생소하지만 x[1]을 기준으로 정렬하는 거야.
lambda는 익명 함수니까 def f(x): return x[1]과 같아.

예시 2: defaultdict(int)

from collections import defaultdict
d = defaultdict(int)
d["a"] += 1
print(d)  # {'a': 1}

KeyError 안 나고 바로 0에서 시작함. int()는 기본값 0.


📌 전략 B: 실전 문제 코드 흐름 분석 훈련

  • 실제 시험 문제 코드를 줄 단위로 의미 분석 + 실행 흐름 디버깅
  • 내가 도와줄 테니까 코드 전체 주고 "이 코드 줄줄이 해석해줘" 하면 해줄게.

✅ 3. 지금부터 같이 할 수 있는 연습 방법

🔸방법 1: 기출문제 코드 분석

예:
“이 정보처리기사 문제 코드 전체 설명해줘”
→ 코드 전체 붙여주면 한 줄씩 상황 흐름 설명해줄게


🔸방법 2: 처음 보는 문법이 있는 코드 주기

예:
“이 문법 처음보는데 해석해줘”
→ 예제 만들고 디버깅 해줄게


🔸방법 3: 자주 나오는 문법 정리 노트 만들기

내가 자주 등장하는 고급 문법이나 자료구조들을
짧은 예제 + 설명 + 시각화 형태로 정리해줄 수 있어


✅ 4. 추천: 지금 연습해볼까요?

너가 지금 겪고 있는 문제를 같이 분석해보자. 예를 들어 이렇게 해줘:

1. 정보처리기사 실기 문제에서 봤던 코드 중 이해 안 된 거 주기
2. 또는 처음 본 문법을 포함한 줄을 주기
3. 또는 “파이썬 실전에서 자주 쓰는 문법들 정리해줘” 요청

🔚 요약

전략내용
고급 문법/자료구조 등장 → 예제로 정복직접 해석 + 예제 + 시각화
실전 코드 → 줄줄이 해석디버깅하듯이 한 줄씩 설명
기출 코드 분석 훈련전체 코드의 흐름을 따라가며 분석
도움 요청 쉽게 하기“이 문법 처음봤어”, “이 코드 해석해줘” 하면 됨

응! 내가 위에서 예시로 든 것들(lambda, defaultdict, deque, sort(key=...), 얕은 복사 등)은 정보처리기사 실기에서 실전 코드에 자주 등장하는 대표적인 파이썬 문법과 자료구조야. 더 구체적으로 말하면:


✅ 정보처리기사 실기 / 실전 코딩테스트에서 자주 등장하는 파이썬 문법 Top 15

범주문법/기능실제 등장 예시
1. 정렬 함수sorted(), sort(key=...), lambda튜플/리스트 정렬 기준 설정
2. 기본 자료구조dict, set, list, tuplekey-value 저장, 중복 제거
3. 고급 자료구조deque, defaultdict, Counter큐, 누적 계수, 자동 초기화
4. 리스트 컴프리헨션[x for x in list if 조건]필터링, 2차원 배열 초기화
5. 조건문과 논리 연산if not A or B우선순위 혼동 주의
6. 얕은 복사/깊은 복사copy(), deepcopy(), [:]리스트 복사 실수 주의
7. 함수 인자 전달*args, **kwargs, def f(*a):다중 인자 함수 호출
8. 람다 함수lambda x: x[1]정렬, 필터링
9. enumerate / zipfor i, v in enumerate(lst)인덱스 + 값 동시에 받기
10. map / filter / reducemap(int, input().split())입력 처리 or 값 변환
11. 예외 처리try: ... except:dict lookup 등에서 사용
12. 모듈 사용heapq, math, collections, itertools우선순위 큐, 조합 생성
13. 슬라이싱arr[::-1], arr[1:-1]문자열/리스트 처리
14. 재귀와 DFS/BFS 패턴visited, dfs(i)연결 요소 찾기, 백트래킹
15. 클래스 / 구조체class Node:객체 단위 정렬, 구성

🔍 예시로 살펴보자

defaultdict(int) vs 일반 dict

from collections import defaultdict
d = defaultdict(int)  # 기본값 0으로 자동 생성됨
d['x'] += 1
print(d)  # {'x': 1}
  • 정보처리기사 실기에서 부품 개수 누적, 카운트용 dict 자주 등장
  • 실수: 일반 dict로 하면 KeyError

lambda x: x[1]을 이용한 정렬

arr = [(1, 2), (3, 1), (5, 4)]
arr.sort(key=lambda x: x[1])
print(arr)  # [(3, 1), (1, 2), (5, 4)]
  • 실기 문제에서 의존성 정렬, 우선순위 정렬 시 자주 나옴

deque (양방향 큐)

from collections import deque
dq = deque([1, 2, 3])
dq.appendleft(0)
dq.pop()
print(dq)  # deque([0, 1, 2])
  • BFS, 스택/큐 시뮬레이션 문제에서 list보다 빠름
  • 실기에서는 from collections import deque부터 꼭 필요

좋아! 지금부터 정보처리기사 실기에서 자주 등장하는 파이썬 문법 중
1번부터 5번까지기초부터 실전 예제, 디버깅 해석까지 줄줄이 설명해줄게.


✅ 1. 정렬 함수: sorted(), sort(), key=..., lambda


🔹1-1 기본 구조

함수특징
sorted(iterable)새로운 정렬된 리스트를 리턴
list.sort()리스트 자체를 제자리 정렬 (in-place)
key 인자정렬 기준을 지정하는 함수
reverse=True내림차순 정렬

🔹1-2 예제 + 해설

arr = [3, 1, 4, 1, 5]
sorted_arr = sorted(arr)   # 정렬된 새로운 리스트 반환
arr.sort(reverse=True)     # 원본 arr 자체를 내림차순 정렬

📌 줄줄이 해석:

arr = [3, 1, 4, 1, 5]  
# 리스트 arr을 생성한다. 초기 상태: [3, 1, 4, 1, 5]

sorted_arr = sorted(arr)
# sorted()는 arr의 복사본을 정렬해서 새 리스트를 반환한다.
# 원본 arr은 변하지 않고, sorted_arr = [1, 1, 3, 4, 5]

arr.sort(reverse=True)
# arr 리스트 자체를 내림차순으로 바꾼다.
# 실행 후 arr = [5, 4, 3, 1, 1]

🔹1-3 실전 응용: key=lambda

data = [(1, 3), (2, 2), (3, 1)]
data.sort(key=lambda x: x[1])

🧠 해설:

  • 각 요소는 튜플 (x, y) 형태
  • key=lambda x: x[1]두 번째 값을 기준으로 정렬

📌 흐름:

data = [(1,3), (2,2), (3,1)]
정렬 기준: x[1] → [3, 2, 1]
정렬 결과: [(3,1), (2,2), (1,3)]

✅ 2. 기본 자료구조: dict, set, list, tuple


🔹2-1 dict (딕셔너리)

d = {'a': 1, 'b': 2}
d['c'] = 3
print(d['a'])  # 1
  • key-value 저장
  • key는 문자열, 숫자 등 불변 자료형만 가능
  • d.get('x', 0)처럼 .get() 쓰면 기본값 설정 가능

🔹2-2 set (집합)

s = set([1, 2, 2, 3])
s.add(4)
s.discard(2)
  • 중복 제거
  • 집합 연산 가능: |, &, -

🔹2-3 list & tuple

lst = [1, 2, 3]
tpl = (1, 2, 3)
  • list: 변경 가능
  • tuple: 변경 불가 → dict key로 사용 가능

✅ 3. 고급 자료구조: deque, defaultdict, Counter


🔹3-1 deque (양방향 큐)

from collections import deque
q = deque([1, 2, 3])
q.append(4)
q.appendleft(0)
print(q)  # deque([0, 1, 2, 3, 4])
q.pop()       # → 4
q.popleft()   # → 0
  • 양쪽 삽입/삭제가 빠름 → 큐, BFS 구현에 필수

🔹3-2 defaultdict

from collections import defaultdict
d = defaultdict(int)
d['x'] += 1
print(d)  # {'x': 1}
  • key가 없을 때 자동으로 int() (0), list() ([]) 등으로 초기화됨
  • d['y'] += 1을 그냥 써도 에러 안 나고 동작함

🔹3-3 Counter (빈도수)

from collections import Counter
c = Counter("banana")
print(c)  # {'a':3, 'b':1, 'n':2}
  • 리스트/문자열 안의 요소 개수 세기 자동화

✅ 4. 리스트 컴프리헨션


🔹4-1 기본형

arr = [x for x in range(5)]
# [0, 1, 2, 3, 4]

🔹4-2 조건 포함

evens = [x for x in range(10) if x % 2 == 0]
# [0, 2, 4, 6, 8]

🔹4-3 2차원 배열 생성

matrix = [[0]*3 for _ in range(4)]
# 4행 3열짜리 0으로 채워진 배열

❗ 실수: [[0]*3]*4는 얕은 복사라 하나만 바뀌어도 전체가 바뀜


✅ 5. 조건문과 논리 연산자


🔹5-1 조건문 구조

if a > 0 and b < 10:
    ...
  • and, or, not 연산 순서 주의
  • not A or BA가 False거나 B가 True이면 True

🔹5-2 우선순위 주의 예시

x = 5
if not x > 10 or x < 7:
    print("yes")

🔍 해석:

  • not x > 10not FalseTrue
  • True or True → 전체가 True → 출력됨

🔹5-3 실기 스타일 if문

if not stack or stack[-1] != val:
    stack.append(val)
  • stack이 비었거나, 맨 위와 값이 다르면 → push
  • 자주 쓰이는 스택 조건문

🧠 요약 테이블

문법설명예시
sort(key=lambda x: ...)기준 지정 정렬정렬 문제
dict, set기본 자료구조누적, 중복 제거
deque, defaultdict, Counter고급 자료구조BFS, 누적 카운트
리스트 컴프리헨션필터링/초기화[x for x in ...]
not A or B조건문 우선순위 주의if not stack or ...

원하는 문법에서 더 깊이 파고들 수 있어.
예를 들어 "not A or B는 아직도 헷갈려" 하면 예제 더 들어줄게.
다음은 6번부터 10번까지 문법 해설로 넘어갈까?

정말 잘 물어봤어! 이 부분은 많은 파이썬 초보자들이 헷갈려서 실수하는 부분이고, 정보처리기사 실기나 실전 코딩에서도 자주 트랩으로 나와.
이제부터 [[0]*3]*4가 왜 문제인지, 그리고 왜 [[0]*3 for _ in range(4)]가 안전한지디버깅 하듯이 해부해서 설명할게.


✅ 상황: 2차원 리스트(행렬)를 만들고 싶을 때


✅ 방법 1 (잘못된 방법) — 얕은 복사

matrix = [[0]*3]*4

📌 뜻:

  • [0]*3[0, 0, 0] 리스트 하나를 만들고
  • 그거를 4번 반복한 것처럼 보이지만, **"같은 리스트를 복사한 것"**이야!

📌 시각적으로 보면 아래와 같아:

matrix = [
    row0 → [0, 0, 0],  ← 모든 row가 같은 리스트를 참조
    row1 → [0, 0, 0],
    row2 → [0, 0, 0],
    row3 → [0, 0, 0]
]

✅ 이때, 만약 하나만 바꾸면?

matrix[0][1] = 99

💥 예상은:

[
    [0, 99, 0],
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
]

❗ 실제 결과는:

[
    [0, 99, 0],
    [0, 99, 0],
    [0, 99, 0],
    [0, 99, 0]
]

왜?
row0, row1, row2, row3같은 리스트 하나를 가리키고 있어서
→ 하나만 바꿨는데 다 같이 바뀐 것처럼 보임


✅ 방법 2 (정답) — 각각 다른 리스트 만들기

matrix = [[0]*3 for _ in range(4)]

📌 이건 리스트 컴프리헨션을 이용해서, 0으로 채워진 리스트4번 새로 생성하는 코드야.

📌 시각적으로 보면:

matrix = [
    row0 → [0, 0, 0],  ← 전부 다른 객체
    row1 → [0, 0, 0],
    row2 → [0, 0, 0],
    row3 → [0, 0, 0]
]

✅ 이 상태에서:

matrix[0][1] = 99

👉 결과:

[
    [0, 99, 0],
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
]

정상적으로 작동하지? 😊


🔍 확인 실험: id()로 비교해보기

m1 = [[0]*3]*4
m2 = [[0]*3 for _ in range(4)]

print(id(m1[0]) == id(m1[1]))  # True → 같은 객체!
print(id(m2[0]) == id(m2[1]))  # False → 서로 다른 객체!

✅ 요약: 왜 [[0]*3]*4가 안 되는가?

잘못된 방식 ([[0]*3]*4)올바른 방식 ([[0]*3 for _ in range(4)])
같은 리스트 4개 참조각각 다른 리스트 생성
수정 시 전체가 바뀜개별 행만 수정 가능
얕은 복사 (shallow copy)독립 객체 생성

💡 정리 문장

리스트 곱하기(*)는 **"객체를 복사"**할 뿐, 새로운 객체를 만들지 않음.
리스트 컴프리헨션은 **"반복마다 새로운 리스트"**를 만들어줌.
2차원 배열은 반드시 컴프리헨션으로 만들어야 안전해!


좋아! 이번엔 너가 요청한 6번부터 8번까지 — 파이썬 실전에서 자주 헷갈리면서도 정보처리기사 실기나 코딩 문제 풀이에 자주 등장하는 문법들을 차례대로 해부해줄게.


✅ 6. 얕은 복사 vs 깊은 복사 (shallow vs deep copy)


🔹6-1 문제 상황부터 살펴보자

a = [[1, 2], [3, 4]]
b = a
b[0][0] = 99
print(a)  # ??

결과:

[[99, 2], [3, 4]]

왜?
ab는 **같은 리스트를 가리키는 포인터(참조)**이기 때문이야.


🔹6-2 copy()는 얕은 복사다!

import copy

a = [[1, 2], [3, 4]]
b = a.copy()
b[0][0] = 99
print(a)  # [[99, 2], [3, 4]] → 여전히 영향을 받음

왜 또 같이 바뀌지?

  • .copy()바깥 리스트만 복사
  • 안쪽 리스트는 원래 것 그대로 참조

📌 시각화:

a  →  [ [1, 2],   [3, 4] ]  
          ↑         ↑
          공유 중  공유 중
b  →  [ [1, 2],   [3, 4] ]

🔹6-3 진짜 완전 복사: deepcopy()

import copy

a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
b[0][0] = 99
print(a)  # [[1, 2], [3, 4]] ← a는 영향 없음!

✅ 내부까지 전부 복사하니까 안전해.


🔹실전 팁

복사 방법영향 여부설명
b = aO같은 객체
b = a.copy()얕은 복사 (1단계만 복사)
b = deepcopy(a)완전 독립 복사

✅ 7. 함수 인자 전달: *args, **kwargs


🔹7-1 기본 개념

def f(*args):
    for x in args:
        print(x)
  • *args: 여러 개의 인자를 받을 수 있음 → 튜플로 전달됨
f(1, 2, 3)
# 출력:
# 1
# 2
# 3

🔹7-2 **kwargs (키워드 인자)

def f(**kwargs):
    for k, v in kwargs.items():
        print(k, v)

f(name="Hansun", age=25)
# name Hansun
# age 25
  • **kwargs: 딕셔너리 형태로 키워드 인자 받음

🔹7-3 함수 호출 시에도 사용 가능

def add(a, b, c):
    return a + b + c

params = [1, 2, 3]
print(add(*params))  # 6

params_dict = {'a': 1, 'b': 2, 'c': 3}
print(add(**params_dict))  # 6
  • *는 리스트나 튜플 → 위치 인자 풀어줌
  • **는 딕셔너리 → 키워드 인자 풀어줌

🔹실전 사용 포인트

구문설명전달 형식
*args여러 개의 값튜플
**kwargs여러 개의 키=값딕셔너리
함수 호출 시 *리스트위치 인자 분해
함수 호출 시 **딕셔너리키워드 인자 분해

✅ 8. 람다 함수 (lambda)


🔹8-1 기본형

f = lambda x: x * 2
print(f(5))  # 10
  • lambda익명 함수 (이름 없는 함수)
  • lambda 인자: 반환값

🔹8-2 정렬에서 자주 사용!

data = [(1, 3), (2, 2), (3, 1)]
data.sort(key=lambda x: x[1])
print(data)  # [(3, 1), (2, 2), (1, 3)]
  • key=lambda x: x[1] → 튜플의 두 번째 값 기준 정렬

🔹8-3 map, filter에서도 사용

nums = [1, 2, 3, 4]
doubled = list(map(lambda x: x*2, nums))
print(doubled)  # [2, 4, 6, 8]

even = list(filter(lambda x: x%2 == 0, nums))
print(even)  # [2, 4]
  • map(func, iterable) → 각각 변형
  • filter(func, iterable) → 조건 통과하는 것만 남김

🔹실전 팁

용도사용 예
정렬key=lambda x: x[1]
맵핑map(lambda x: x+1, arr)
필터링filter(lambda x: x > 0, arr)

✅ 요약 정리표

항목핵심 내용실수 포인트
얕은/깊은 복사copy() vs deepcopy()내부 구조가 리스트면 반드시 deepcopy
*args / **kwargs다중 인자 처리호출할 때도 *, ** 써야 함
lambda 함수짧은 익명 함수주로 정렬, map, filter에서 사용

0개의 댓글