Skip to content
This page has been auto-translated and may contain errors.View in English

버그하우스

축하합니다. 당신은 Crooked Orbit의 기술 책임자가 되었습니다. 이곳은 의심스러운 우주비행사들과 더 의심스러운 코드로 운영되는 작고 약간 혼란스러운 우주 물류 회사입니다.

급여는 괜찮습니다. 코드베이스는 그렇지 않고요...

당신의 일은 이 문제들을 해결하는 것입니다: 버그, 망가진 함수, 기술적으로는 실행되지만 정말 그래선 안 되는 것들.

#1: 이름 포매터

Pip 저기, 제가 이름 포매터를 만들었는데요, 그냥... 아무 일도 안 일어나요? 😭 에러 없이 잘 돌아가긴 하는데, 이름이 여전히 다 소문자예요. 각각에 .capitalize()를 호출하고 있고, 루프 안에 분명히 보이는데요. 이해가 안 돼요. 좀 봐주실 수 있나요?
python
def format_name(full_name):
    parts = full_name.split()
    for part in parts:
        part = part.capitalize()
    return " ".join(parts)

print(format_name("alice van den berg"))

기대 결과: Alice Van Den Berg

실제 결과: alice van den berg

무엇이 잘못되었고, 어떻게 고칠 수 있을까요?

힌트

for 루프 안에서 변수를 재할당하면 실제로 어떤 일이 일어나는지 생각해보세요. part를 바꾸면 그것이 나온 리스트에 영향을 줄까요?

해결 방법 한 가지

for part in parts라고 쓰면 Python은 리스트의 항목을 하나씩 차례로 줍니다. part는 현재 항목을 담고 있는 임시 변수일 뿐이에요. 리스트 자체와 직접 연결된 것이 아닙니다.

그래서 part = part.capitalize()라고 쓰면 part가 가리키는 것을 바꾸는 것일 뿐이에요. parts는 여전히 원래 문자열들을 가지고 있습니다. 리스트는 실제로 바뀐 적이 없어요.

이걸 명확하게 보여주는 예시입니다:

python
parts = ["alice", "van", "den", "berg"]

for part in parts:
    part = part.capitalize()

print(parts)
# ['alice', 'van', 'den', 'berg']  # 아무것도 바뀌지 않음

해결하려면 대문자화된 값으로 새로운 리스트를 만들어야 합니다. 리스트 컴프리헨션이 이걸 깔끔하게 해줍니다:

python
def format_name(full_name):
    parts = full_name.split()
    return " ".join(part.capitalize() for part in parts)

print(format_name("alice van den berg"))
# Alice Van Den Berg

part.capitalize() for part in parts는 각 이름을 거치면서 대문자화하고, 결과를 새로운 리스트로 모읍니다. 그런 다음 .join()이 공백으로 다시 합쳐줍니다.

#2: 최고 점수

Zee 좀 부끄러운데요, 리스트에서 가장 높은 점수를 찾아야 하는 함수를 만들었는데 그냥... None을 출력해요? 매번요. 루프를 다섯 번이나 검토해봤는데 로직은 괜찮아 보여요. 점수는 분명히 들어있고요. 무슨 일인지 모르겠어요 😅
python
def highest_score(scores):
    best = 0
    for score in scores:
        if score > best:
            best = score

results = [45, 92, 78, 88, 65]
print(f"Top score: {highest_score(results)}")

기대 결과: Top score: 92

실제 결과: Top score: None

무엇이 잘못되었고, 어떻게 고칠 수 있을까요?

힌트

return 문을 작성하지 않으면 함수는 무엇을 반환할까요?

해결 방법 한 가지

루프는 괜찮습니다. 로직도 괜찮아요. 문제는 highest_score가 실제로 아무것도 돌려주지 않는다는 거예요. 최고 점수를 찾고는 그걸로 아무것도 하지 않습니다.

Python에서 함수에 return 문이 없으면 자동으로 None을 반환합니다. 그게 바로 당신이 출력하고 있는 것이에요.

수정은 마지막 한 줄이면 됩니다:

python
def highest_score(scores):
    best = 0
    for score in scores:
        if score > best:
            best = score
    return best

results = [45, 92, 78, 88, 65]
print(f"Top score: {highest_score(results)}")
# Top score: 92

이건 자주 발생합니다. 로직이 다 있어서 함수가 완성된 것처럼 보이지만, return이 없으면 함수가 끝날 때 결과가 그냥 사라져버립니다.

#3: 예산 체크

Orla 좋아요, 그래서 작은 예산 추적기를 만들고 있는데 숫자를 입력할 때마다 충돌해요. 그 숫자로 뭘 하지도 않고 그냥 즉시 TypeError로 터져버려요. 로직을 확인해봤는데 괜찮아 보이는데요? threshold는 float이고 입력도 숫자고... 뭘 불평하는 건지... 도와주세요
python
def check_budget(threshold):
    spent = input("How much have you spent? ")
    if spent >= threshold:
        print("Over budget!")
    else:
        print("You're within budget.")

check_budget(500.0)

에러:

TypeError: '>=' not supported between instances of 'str' and 'float'

무엇이 잘못되었고, 어떻게 고칠 수 있을까요?

힌트

input()은 사용자가 무엇을 입력하든 상관없이 항상 어떤 타입을 반환하나요?

해결 방법 한 가지

input()은 항상 문자열을 반환합니다. 사용자가 숫자를 입력했는지는 상관없어요. Python은 그걸 모르거든요. 입력된 것을 그냥 텍스트로 돌려줄 뿐입니다.

그래서 코드가 spent >= threshold를 비교하려고 할 때 문자열과 float를 비교하게 되고, Python은 그걸 거부합니다. 그게 바로 TypeError예요.

해결책은 비교하기 전에 입력값을 숫자로 변환하는 것입니다. 소수점 값을 처리하려면 float()를 사용하세요:

python
def check_budget(threshold):
    spent = float(input("How much have you spent? "))
    if spent >= threshold:
        print("Over budget!")
    else:
        print("You're within budget.")

check_budget(500.0)
# How much have you spent? 620
# Over budget!

input()float()로 감싸면 문자열이 바로 숫자로 변환되어 비교가 예상대로 작동합니다.

이건 Python에서 가장 흔한 혼란 중 하나입니다: input()은 숫자를 읽는 것처럼 보이지만 항상 문자열을 줍니다. 직접 변환해야 합니다.

#4: 화물 라벨

Dex 화물 명세서용으로 라벨을 생성하고 있는데 이 한 줄에서 계속 충돌해요. 아이템 이름은 문자열이고 무게는 숫자인데, 괜찮아 보이지 않나요? 그런데 Python이 문자열 연결 때문에 난리를 칩니다 😩
python
def cargo_label(item, weight):
    label = "Item: " + item + " | Weight: " + weight + "kg"
    return label

print(cargo_label("Moon rocks", 42))

에러:

TypeError: can only concatenate str (not "int") to str

무엇이 잘못되었고, 어떻게 고칠 수 있을까요?

힌트

Python의 + 연산자는 숫자를 자동으로 문자열로 변환하지 않습니다. 합치기 전에 무엇을 해야 할까요?

해결 방법 한 가지

Python에서 +로 문자열을 합칠 때는 모든 값이 문자열이어야 합니다. weight는 정수이기 때문에 Python은 그것을 주변 텍스트에 붙이는 방법을 모릅니다. 추측하지 않고 거부합니다.

해결책은 str()weight를 문자열로 변환하는 것입니다:

python
def cargo_label(item, weight):
    label = "Item: " + item + " | Weight: " + str(weight) + "kg"
    return label

print(cargo_label("Moon rocks", 42))
# Item: Moon rocks | Weight: 42kg

이런 경우에는 f-string이 더 깔끔합니다. 변환을 알아서 처리해주니까요:

python
def cargo_label(item, weight):
    return f"Item: {item} | Weight: {weight}kg"

print(cargo_label("Moon rocks", 42))
# Item: Moon rocks | Weight: 42kg

{} 안에서 Python은 값을 자동으로 문자열 표현으로 변환합니다. 그래서 str()이 전혀 필요 없어요.

#5: 승객 명단

Cass 정말 이상한 일이 일어나고 있어요. 각 비행편의 승객 명단을 만드는 함수가 있는데, 첫 번째 비행편은 괜찮아 보여요. 그런데 세 번째쯤 되면 명단에 이전 모든 비행편의 사람들도 다 들어가 있어요? 호출 사이에 데이터를 공유하지 않거든요, 각각이 완전히 별개예요. 도대체 무슨 일인지 정말 모르겠어요 😰
python
def build_manifest(name, passengers=[]):
    passengers.append(name)
    return passengers

flight_1 = build_manifest("민준")
flight_2 = build_manifest("서연")
flight_3 = build_manifest("지호")

print(flight_1)
print(flight_2)
print(flight_3)

기대 결과:

['민준']
['서연']
['지호']

실제 결과:

['민준']
['민준', '서연']
['민준', '서연', '지호']

무엇이 잘못되었고, 어떻게 고칠 수 있을까요?

힌트

Python의 기본 인자 값은 함수가 정의될 때 한 번만 평가됩니다. 함수가 호출될 때마다가 아니에요. 리스트 같은 가변 객체에 대해서는 이게 무엇을 의미할까요?

해결 방법 한 가지

이건 Python에서 가장 유명한 함정 중 하나입니다. passengers=[]를 기본 인자로 쓰면 Python은 함수가 정의될 때 그 리스트를 한 번만 만듭니다. 기본값을 사용하는 모든 호출은 정확히 똑같은 리스트 객체를 공유합니다. 그래서 한 호출에서 리스트에 추가하면 이후의 모든 호출에 영향을 줍니다.

표준 해결책은 기본값으로 None을 사용하고 함수 안에서 새 리스트를 만드는 것입니다:

python
def build_manifest(name, passengers=None):
    if passengers is None:
        passengers = []
    passengers.append(name)
    return passengers

flight_1 = build_manifest("민준")
flight_2 = build_manifest("서연")
flight_3 = build_manifest("지호")

print(flight_1)  # ['민준']
print(flight_2)  # ['서연']
print(flight_3)  # ['지호']

이제 리스트를 전달하지 않는 각 호출은 완전히 새로운 자신만의 리스트를 갖게 됩니다.

이건 모든 가변 기본값에 적용됩니다: 리스트, 딕셔너리, 집합. 매번 새로운 것을 원한다면 시그니처에 두지 마세요. None을 사용하고 함수 안에서 생성하세요.