좋아요! 정보처리기사 실기에서는 기본 문법이나 자주 쓰이는 기능을 헷갈리게 꼬아서 출제하는 문제가 많습니다. 예를 들어 변수의 범위(scope), 참조/복사 차이, 조건문의 흐름, 반복문의 탈출 조건 등 기본 문법이지만 조금만 꼬면 틀리게 되는 것들이죠.
다음 파이썬 코드를 실행했을 때 출력 결과는 무엇일까요?
def modify_list(lst):
lst.append(4)
lst = [1, 2, 3]
lst.append(5)
my_list = [0]
modify_list(my_list)
print(my_list)
A. [0, 4, 5]
B. [0, 4]
C. [0, 4, 1, 2, 3, 5]
D. [1, 2, 3, 5]
이 코드는 리스트를 함수에 인자로 넘길 때 참조/복사 관계와 **지역 변수의 스코프(scope)**를 묻는 문제입니다.
def modify_list(lst):
lst.append(4) # (1)
lst = [1, 2, 3] # (2)
lst.append(5) # (3)
lst.append(4)lst는 함수 호출 시 my_list를 그대로 참조하고 있음my_list = [0] → lst.append(4)를 하면 my_list = [0, 4]가 됨lst = [1, 2, 3]lst는 새로운 리스트 [1, 2, 3]을 가리키도록 다시 할당lst는 더 이상 my_list를 참조하지 않음my_list와 lst는 갈라짐lst.append(5)lst는 [1, 2, 3]이므로 → [1, 2, 3, 5]가 되지만my_list = [0]
modify_list(my_list)
print(my_list)
modify_list 함수 안에서 my_list는 [0] → [0, 4]로 변경됨my_list와 관계없음[0, 4]좋아! 이번엔 네가 요청한 딕셔너리, set, 객체 관련해서 정보처리기사 실기에서 헷갈리도록 꼬는 유형으로 문제를 3개 낼게. 각 문제는 "틀릴 수밖에 없는 기본기 트랩"을 주제로 구성했고, 각 문제 뒤에 풀이와 완전 해부 해설을 붙였어.
class Item:
def __init__(self, name):
self.name = name
item1 = Item("apple")
item2 = Item("apple")
d = {}
d[item1] = 100
d[item2] = 200
print(len(d))
A. 1
B. 2
C. 에러 발생
D. None
item1과 item2는 name이 같아도 다른 객체__hash__()와 __eq__()를 기준으로 키를 비교함Item은 __hash__()나 __eq__()를 오버라이드하지 않았기 때문에,즉:
id(item1) != id(item2)
hash(item1) != hash(item2)
그래서 d에는 서로 다른 두 키가 들어가므로 len(d) = 2
__hash__, __eq__**를 반드시 오버라이드해야 키 충돌을 제대로 처리함!a = [1, 2]
b = [1, 2]
s = set()
s.add(tuple(a))
s.add(tuple(b))
print(len(s))
A. 1
B. 2
C. TypeError
D. None
a와 b는 리스트지만, 리스트는 set에 넣을 수 없음 → 가변(mutable) 타입이기 때문tuple()로 바꿔서 넣음 → tuple(a) = (1, 2)하지만 tuple(a)와 tuple(b)는 내용이 같고, 불변형이라 해시값도 같음
tuple(a) == tuple(b) → True
hash(tuple(a)) == hash(tuple(b)) → True
그래서 set 안에선 중복으로 판단 → 한 개만 저장됨
set은 중복 제거 + 해시 가능한(불변) 자료형만 저장 가능class Person:
def __init__(self, hobbies=[]):
self.hobbies = hobbies
p1 = Person()
p2 = Person()
p1.hobbies.append("coding")
print(p2.hobbies)
A. []
B. ['coding']
C. ['coding', 'coding']
D. 에러 발생
__init__(self, hobbies=[]) 는 한 번 생성된 [] 리스트 객체를 여러 인스턴스에서 공유p1.hobbies.append("coding") 하면 p2.hobbies도 똑같은 리스트 참조 중p1.hobbies is p2.hobbies → True
기본 인자로 None을 주고, 내부에서 새 리스트를 만드는 방식이 안전함:
class Person:
def __init__(self, hobbies=None):
if hobbies is None:
self.hobbies = []
else:
self.hobbies = hobbies
[], {} 등 가변 객체 쓰면 함정좋아, 지금부터 요청한 3개 주제 —
각각 대표적인 트랩 문제 하나씩 출제하고, 초보자도 완벽하게 이해할 수 있도록 각 줄 해설 + 값 추적 + 핵심 요약까지 해줄게.
def update(x, y):
x += y
y += x
a = [1, 2]
b = [3, 4]
update(a, b)
print(a)
A. [1, 2, 3, 4]
B. [1, 2]
C. [1, 2, 3, 4, 1, 2]
D. [1, 2, 3, 4]
def update(x, y):
x += y # x = x + y → 리스트이므로 x.extend(y)
y += x # y = y + x → 새 리스트 만들어서 y에 할당 (지역 변수 y)
x += y는 리스트의 in-place 연산 (수정됨)y += x는 지역변수 y만 바뀌고, 외부 변수 b는 영향 X# 처음 상태:
a = [1, 2]
b = [3, 4]
# update(a, b) 호출 후:
a → [1, 2, 3, 4]
b → 변함 없음
x += y는 참조된 원본을 수정y += x는 새 객체가 y에 할당될 뿐, 원본에는 영향 Xfuncs = []
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는 함수를 만드는 코드인데i를 공유하고 있고, 마지막엔 i = 2# funcs = [<lambda: i>, <lambda: i>, <lambda: i>]
# 나중에 실행되면 모두 i == 2
for i in range(3):
funcs.append(lambda i=i: i)
i=i로 기록 시점의 값을 고정시킬 수 있음lambda는 변수를 캡처하지만 값은 캡처하지 않음x = 'global'
lst = [x for x in range(3)]
print(x)
A. 'global'
B. 2
C. 3
D. 에러 발생
x = 'global' # 전역 x = 'global'
lst = [x for x in range(3)] # 여기 x는 리스트 컴프리헨션 내부의 지역 변수
x는 외부 x와는 완전히 다른 변수x는 변경되지 않음| 트랩 유형 | 핵심 함정 | 기억 포인트 |
|---|---|---|
| 함수 인자 (값 vs 참조) | += 같은 연산의 행동이 자료형마다 다름 | 리스트는 in-place 변경됨 |
| for + lambda 클로저 | 루프 변수는 나중에 실행할 때 참조됨 | lambda i=i로 고정 |
| 리스트 컴프리헨션 스코프 | 컴프리헨션 내부 변수는 외부 변수에 영향 안 줌 | 파이썬 3부터는 자체 스코프 |