아주 좋아! 지금부터 요청한 4가지 주제는 모두 파이썬 실무·정보처리기사 실기에서도 틀리기 쉬운 트랩이야. 각각을 다음 형식으로 완전 해부해서 설명해줄게:
for-else 구문 오해 트랩for i in range(5):
if i == 3:
break
else:
print("완료")
A. 아무것도 출력되지 않는다
B. "완료"
C. 3
D. 에러 발생
for i in range(5):
if i == 3:
break # ❗️break 실행 → else 실행 안 됨
else:
print("완료") # 🔥 for문이 끝까지 도는 경우에만 실행됨
else는 반복문이 "정상적으로 끝났을 때만" 실행됨break로 빠져나오면 → else는 무시됨| 구문 | 의미 |
|---|---|
for ... → else: | 반복문이 끝까지 돌아갔을 때만 실행 |
break 발생 시 | else는 실행되지 않음 |
enumerate() 사용 오류 트랩words = ["apple", "banana", "cherry"]
for i in enumerate(words):
print(i)
A. "apple", "banana", "cherry"
B. 0 apple, 1 banana, 2 cherry
C. (0, 'apple'), (1, 'banana'), (2, 'cherry')
D. 에러 발생
for i in enumerate(words):
print(i)
enumerate()는 (인덱스, 값)의 튜플을 반환i는 한 줄씩 (index, word) 형식으로 받아서 출력됨(0, 'apple')
(1, 'banana')
(2, 'cherry')
i, word in enumerate(words):를 쓰려면 언패킹 해야 함for index, value in enumerate(lst):
...
enumerate()는 튜플 반환 → 언패킹 필요set에서 add() vs update() 혼동 트랩s = set()
s.add("abc")
s.update("xyz")
print(s)
A. {'abc', 'xyz'}
B. {'a', 'b', 'c', 'x', 'y', 'z'}
C. {'abc', 'x', 'y', 'z'}
D. 에러 발생
s.add("abc") # 전체 문자열을 하나의 원소로 추가 → "abc"
s.update("xyz") # 문자열은 이터러블 → 문자 하나하나 쪼개서 추가됨
# 결과: {'abc', 'x', 'y', 'z'}
add()는 한 개 원소를 통째로 넣음update()는 이터러블의 각 원소를 따로 넣음s.update(["hi", "bye"]) → {"hi", "bye"} ✅
s.update("hi") → {"h", "i"} ❗️쪼개짐
| 메서드 | 동작 방식 |
|---|---|
add(x) | x 그대로 한 원소 추가 |
update(iterable) | iterable의 각 요소를 개별 추가 |
dict.get()의 default 값 처리 트랩d = {"a": 1}
print(d.get("b", 2))
print(d["b"])
A. 2, 에러
B. 2, None
C. None, 에러
D. 에러, 에러
d.get("b", 2) # key "b"가 없으므로 default 2 반환 ✅
d["b"] # ❗️KeyError 발생
dict.get(key, default)는 존재하지 않으면 default 반환dict[key]는 존재하지 않으면 예외 발생| 구문 | 없을 때 동작 |
|---|---|
d.get("k", val) | val 반환 |
d["k"] | KeyError 발생 |
| 트랩 유형 | 실수 | 안전한 이해 |
|---|---|---|
for-else | break와 관계 없이 else 실행될 거라 착각 | else는 break 없이 끝났을 때만 실행 |
enumerate() | 언패킹 안 함 | for idx, val in enumerate() |
set.add() vs update() | 문자열 쪼개짐 예상 못 함 | update()는 이터러블 요소 하나하나 |
dict.get() | get과 직접 접근 차이 무시 | get()은 default, []는 예외 발생 |
좋아! 이번엔 고급 기초 개념이지만 실전 코딩 트랩에서 엄청 자주 헷갈리는 4가지 주제를 완전 해부해서 보여줄게.
모두 실기시험에서 코드를 빠르게 읽을 수 있어야 하는 부분이니, 아래 순서대로 천천히 따라가면 돼:
lambda와 클로저 변수 캡처 트랩funcs = []
for i in range(3):
funcs.append(lambda: i)
results = [f() for f in funcs]
print(results)
A. [0, 1, 2]
B. [2, 2, 2]
C. [0, 0, 0]
D. 에러 발생
for i in range(3):
funcs.append(lambda: i) # lambda가 i를 캡처하지만 **값이 아니라 변수 참조**
lambda는 i의 "현재 값"이 아니라, "i라는 변수 자체"를 기억함funcs에 있는 lambda들은 모두 동일한 i를 바라봄for i in range(3):
funcs.append(lambda i=i: i) # i의 값을 매개변수 기본값으로 **복사**
| 형태 | 결과 |
|---|---|
lambda: i | 변수 참조 → 값이 변하면 모두 영향 |
lambda i=i: | 값 복사 → 안전하게 고정 |
defaultdict 사용 실수 트랩from collections import defaultdict
d = defaultdict(list)
d["a"].append(1)
d["b"] += [2]
print(d)
A. {'a': [1], 'b': [2]}
B. {'a': [1]}
C. {'a': [1], 'b': 2}
D. 에러 발생
d = defaultdict(list) # ❗️키가 없을 경우 자동으로 list() 생성
d["a"].append(1) → 없던 키 "a" 자동 생성 후 [1] 저장d["b"] += [2] → d["b"] = d["b"] + [2] 이지만d["b"]가 없으면 list()가 자동으로 생성 → [] + [2] = [2]# 실제 동작
d["b"] = [] + [2] = [2]
| 키 접근 | 결과 |
|---|---|
d["x"] | 키가 없어도 list() 기본값으로 자동 생성됨 |
+= | 내부적으로 d["x"] = d["x"] + ...로 동작 가능 |
zip()과 리스트 길이 차이 트랩a = [1, 2, 3]
b = ['a', 'b']
z = list(zip(a, b))
print(z)
A. [(1, 'a'), (2, 'b'), (3, None)]
B. [(1, 'a'), (2, 'b'), (3, '')]
C. [(1, 'a'), (2, 'b')]
D. 에러 발생
zip()은 여러 시퀀스를 병렬로 묶는데, 가장 짧은 길이에 맞춰 동작함a = [1, 2, 3]
b = ['a', 'b']
zip(a, b) → [(1, 'a'), (2, 'b')]
3은 쌍이 맞는 요소가 없어서 생략됨from itertools import zip_longest
zip_longest(a, b, fillvalue=None)
| 함수 | 길이 동작 방식 |
|---|---|
zip() | 짧은 쪽에 맞춰 자름 |
zip_longest() | 긴 쪽 기준, 채워서 이어줌 |
sorted()의 key 함수 트랩words = ["banana", "Apple", "cherry"]
print(sorted(words))
print(sorted(words, key=str.lower))
A. ['Apple', 'banana', 'cherry'] / ['Apple', 'banana', 'cherry']
B. ['Apple', 'banana', 'cherry'] / ['banana', 'Apple', 'cherry']
C. ['Apple', 'banana', 'cherry'] / ['Apple', 'cherry', 'banana']
D. ['Apple', 'banana', 'cherry'] / ['apple', 'banana', 'cherry']
sorted(words) → 대소문자 구분 O → 유니코드 기준 (A < a)
sorted(words, key=str.lower) → 전부 소문자로 보고 정렬
sorted()는 기본적으로 ASCII/유니코드 순서str.lower를 key로 넘기면 모두 소문자 취급['banana', 'Apple', 'cherry']
# ASCII 기준 → A < b < c → 'Apple' 먼저 나옴
# key=str.lower → ['apple', 'banana', 'cherry']
# 원래 단어 순서 유지하면서 비교용으로만 바꿈
| 정렬 방식 | 설명 |
|---|---|
sorted() | 기본 정렬 (대소문자 구분) |
sorted(key=str.lower) | 모두 소문자 취급 → 대소문자 무시 정렬 |
| 트랩 | 핵심 실수 | 올바른 개념 |
|---|---|---|
| lambda 클로저 | 값이 아닌 변수 참조됨 | lambda i=i로 캡처 |
| defaultdict | 자동 생성되는 구조 오해 | d[x] += ...도 동작 |
| zip() | 길이 차이 무시 | 짧은 쪽 기준 |
| sorted() + key | key의 반환값 기준 정렬 오해 | key=는 비교용 값 지정만 함 |
훌륭한 주제들이야! 지금부터 아래 5가지 트랩을 각각 실전 문제 + 줄 단위 해설 + 개념 요약으로 완전 정리해줄게.
reversed() vs 슬라이싱 혼동 트랩a = [1, 2, 3, 4]
b = reversed(a)
a.append(5)
print(list(b))
A. [4, 3, 2, 1]
B. [5, 4, 3, 2, 1]
C. [5, 4, 3, 2]
D. [4, 3, 2, 1, 5]
a = [1, 2, 3, 4]
b = reversed(a) # ❗️reversed는 '뷰(view)' → 즉시 복사 X
a.append(5) # a가 바뀌어도 b는 영향 ❌
print(list(b)) # reversed는 생성 당시 상태인 [4, 3, 2, 1]
reversed()는 리스트를 즉시 복사하는 게 아니라,append(5)는 반영되지 않음| 방법 | 특징 |
|---|---|
reversed(lst) | 읽기 전용 뷰 객체 생성 |
lst[::-1] | 새 리스트 복사해서 역순 반환 |
any() vs all() 논리 트랩lst = [0, "", [], 42]
print(any(lst))
print(all(lst))
A. True, False
B. True, True
C. False, True
D. False, False
any(iterable) → 하나라도 **참(True)**이면 Trueall(iterable) → 전부가 참이어야 Truelst = [0, "", [], 42]
# False, False, False, True
any(lst) → 하나라도 참인 요소 있음 (42) → ✅ Trueall(lst) → 하나라도 거짓(0, "", []) → ❌ False| 함수 | 의미 | 예시 결과 |
|---|---|---|
any() | 하나라도 참이면 True | any([0, "", 1]) → True |
all() | 모두 참이어야 True | all([1, 2, 0]) → False |
range() 마지막 값 포함 여부 트랩for i in range(1, 5):
print(i, end=" ")
A. 1 2 3 4 5
B. 1 2 3 4
C. 1 2 3
D. 에러
range(start, end)는 start 이상, end 미만1 <= i < 5range(1, 5) → [1, 2, 3, 4]
| 표현 | 결과 |
|---|---|
range(a, b) | a부터 b-1까지 |
| 포함되는 숫자 수 | b - a 개 |
filter() 함수 조건 오해 트랩lst = [1, 2, 3, 4]
def f(x):
return x % 2
print(list(filter(f, lst)))
A. [2, 4]
B. [1, 3]
C. [1, 2, 3, 4]
D. []
filter(func, iterable)은 func(x)가 True인 요소만 반환x % 2는 홀수일 때 True (1), 짝수일 때 False (0)f(1) = 1 → ✅ 포함
f(2) = 0 → ❌ 제외
f(3) = 1 → ✅ 포함
f(4) = 0 → ❌ 제외
| 함수 | 결과 |
|---|---|
filter(f, xs) | f(x)가 True인 x만 남김 |
x % 2 | 홀수만 True 반환 |
try-except 블록 내 변수 유효 범위 트랩try:
x = 1 / 0
except ZeroDivisionError:
err = "error"
print(err)
A. "error"
B. None
C. 에러 발생
D. ZeroDivisionError
try:
x = 1 / 0 # ❗️ZeroDivisionError 발생
except ZeroDivisionError:
err = "error" # except 실행됨 → err 정의됨
print(err) # ✅ "error" 출력
try-except 내부에서 정의한 변수는 바깥에서도 접근 가능| 구문 | 유효 범위 |
|---|---|
if, for, try 등 | ❗️블록 단위 X → 변수는 함수 전체에서 유효 |
| 함수 안에서 선언한 변수 | 함수 밖에서는 접근 불가 |
| 트랩 주제 | 핵심 포인트 | 안전한 이해 |
|---|---|---|
reversed() vs 슬라이싱 | reversed()는 뷰 객체 | 복사하려면 [::-1] |
any() vs all() | 참/거짓 평가 차이 | 1개라도 True → any(), 모두 True → all() |
range() 마지막 포함 여부 | end 미포함 | range(a, b)는 a부터 b-1 |
filter() 조건 오해 | True인 요소만 반환 | 함수 결과가 Boolean이어야 함 |
try-except 변수 범위 | 블록 스코프 X | except 안 변수도 바깥에서 유효 |