해시 연습 5(여러 메서드)

류한선·2025년 7월 3일

실기연습-2

목록 보기
79/95

아주 좋아! 지금부터 요청한 4가지 주제는 모두 파이썬 실무·정보처리기사 실기에서도 틀리기 쉬운 트랩이야. 각각을 다음 형식으로 완전 해부해서 설명해줄게:


🧨 1. for-else 구문 오해 트랩

for i in range(5):
    if i == 3:
        break
else:
    print("완료")

보기:

A. 아무것도 출력되지 않는다
B. "완료"
C. 3
D. 에러 발생


✅ 정답: A. 아무것도 출력되지 않는다


🔍 해설:

for i in range(5):
    if i == 3:
        break        # ❗️break 실행 → else 실행 안 됨
else:
    print("완료")    # 🔥 for문이 끝까지 도는 경우에만 실행됨
  • else는 반복문이 "정상적으로 끝났을 때만" 실행됨
  • break로 빠져나오면 → else는 무시됨

💡 요약:

구문의미
for ...else:반복문이 끝까지 돌아갔을 때만 실행
break 발생 시else는 실행되지 않음

🧨 2. 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. 에러 발생


✅ 정답: C. (0, 'apple'), (1, 'banana'), (2, 'cherry')


🔍 해설:

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()는 튜플 반환 → 언패킹 필요

🧨 3. 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. 에러 발생


✅ 정답: C. {'abc', 'x', 'y', 'z'}


🔍 해설:

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의 각 요소를 개별 추가

🧨 4. dict.get()의 default 값 처리 트랩

d = {"a": 1}
print(d.get("b", 2))
print(d["b"])

보기:

A. 2, 에러
B. 2, None
C. None, 에러
D. 에러, 에러


✅ 정답: A. 2, 에러


🔍 해설:

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-elsebreak와 관계 없이 else 실행될 거라 착각else는 break 없이 끝났을 때만 실행
enumerate()언패킹 안 함for idx, val in enumerate()
set.add() vs update()문자열 쪼개짐 예상 못 함update()는 이터러블 요소 하나하나
dict.get()get과 직접 접근 차이 무시get()은 default, []는 예외 발생

좋아! 이번엔 고급 기초 개념이지만 실전 코딩 트랩에서 엄청 자주 헷갈리는 4가지 주제를 완전 해부해서 보여줄게.
모두 실기시험에서 코드를 빠르게 읽을 수 있어야 하는 부분이니, 아래 순서대로 천천히 따라가면 돼:


🧨 1. 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. 에러 발생


✅ 정답: B. [2, 2, 2]


🔍 해설

for i in range(3):
    funcs.append(lambda: i)   # lambda가 i를 캡처하지만 **값이 아니라 변수 참조**
  • lambda는 i의 "현재 값"이 아니라, "i라는 변수 자체"를 기억함
  • 그래서 funcs에 있는 lambda들은 모두 동일한 i를 바라봄
  • 반복문 종료 후 i = 2 → 모든 lambda가 2를 반환

✔️ 해결법:

for i in range(3):
    funcs.append(lambda i=i: i)  # i의 값을 매개변수 기본값으로 **복사**

💡 요약:

형태결과
lambda: i변수 참조 → 값이 변하면 모두 영향
lambda i=i:값 복사 → 안전하게 고정

🧨 2. 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. 에러 발생


✅ 정답: A. {'a': [1], 'b': [2]}`


🔍 해설

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"] + ...로 동작 가능

🧨 3. 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. 에러 발생


✅ 정답: C. [(1, 'a'), (2, 'b')]


🔍 해설

  • 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()긴 쪽 기준, 채워서 이어줌

🧨 4. 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']


✅ 정답: A. ['Apple', 'banana', 'cherry'] / ['Apple', 'banana', 'cherry']


🔍 해설

sorted(words) → 대소문자 구분 O → 유니코드 기준 (A < a)
sorted(words, key=str.lower) → 전부 소문자로 보고 정렬
  • sorted()는 기본적으로 ASCII/유니코드 순서
  • str.lowerkey로 넘기면 모두 소문자 취급
['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() + keykey의 반환값 기준 정렬 오해key=는 비교용 값 지정만 함

훌륭한 주제들이야! 지금부터 아래 5가지 트랩을 각각 실전 문제 + 줄 단위 해설 + 개념 요약으로 완전 정리해줄게.


🧨 1. 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. [4, 3, 2, 1]


🔍 해설

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]새 리스트 복사해서 역순 반환

🧨 2. any() vs all() 논리 트랩

lst = [0, "", [], 42]
print(any(lst))
print(all(lst))

보기:

A. True, False
B. True, True
C. False, True
D. False, False


✅ 정답: A. True, False


🔍 해설

  • any(iterable) → 하나라도 **참(True)**이면 True
  • all(iterable) → 전부가 참이어야 True
lst = [0, "", [], 42]
# False, False, False, True
  • any(lst) → 하나라도 참인 요소 있음 (42) → ✅ True
  • all(lst) → 하나라도 거짓(0, "", []) → ❌ False

💡 요약

함수의미예시 결과
any()하나라도 참이면 Trueany([0, "", 1]) → True
all()모두 참이어야 Trueall([1, 2, 0]) → False

🧨 3. 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. 에러


✅ 정답: B. 1 2 3 4


🔍 해설

  • range(start, end)start 이상, end 미만
  • 즉, 1 <= i < 5
range(1, 5)[1, 2, 3, 4]

💡 요약

표현결과
range(a, b)a부터 b-1까지
포함되는 숫자 수b - a

🧨 4. 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. []


✅ 정답: B. [1, 3]


🔍 해설

  • 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 반환

🧨 5. try-except 블록 내 변수 유효 범위 트랩

try:
    x = 1 / 0
except ZeroDivisionError:
    err = "error"
print(err)

보기:

A. "error"
B. None
C. 에러 발생
D. ZeroDivisionError


✅ 정답: A. "error"


🔍 해설

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 변수 범위블록 스코프 Xexcept 안 변수도 바깥에서 유효

0개의 댓글