31.4 연습문제 질문이요!
, 안 유진님이 작성 안녕하세요, 저는 31.4 연습문제 답안을 아래와 같이 생각했고, 답안으로 False와 None이 출력됐습니다. 아무리봐도 None인 경우가 없는데 왜 그런지 답안과 비교해봤더니 재귀호출하는게 아니고 재귀호출한 결과를 반환하더라구요. 그래서 제 코드에서 is_palindrome(word)를 return is_palindrome(word)로 바꿨을 때 True가 출력되는 것을 확인했습니다.
그런데 return하게 되면 return 값을 반환하면서 함수가 끝나게 된다고 알고있는데 왜 len(word) == 1인 조건을 만족했을 때 True를 반환하며 끝나지 않고 is_palindrome(l)이 실행되는지 궁급합니다.
def is_palindrome(word):
word = list(word)
if word[0] == word[-1]:
del word[0]
del word[-1]
if len(word) == 1:
return True
is_palindrome(word)
else:
return False
print(is_palindrome('hello'))
print(is_palindrome('level'))
Re: 31.4 연습문제 질문이요!
, 도장_ 관리자님이 작성문의 글에 올린 코드가 들여쓰기가 정확하지 않아서 임의로 수정해서 검토해봤지만 False입니다.
포럼 상단 고정에서 파이썬 시각화를 이용해서 한 단계씩 실행해보면서 바뀌는 내용을 확인해보는 게 좋을 것 같습니다.
Re: 31.4 연습문제 질문이요!
, 안 유진님이 작성앗 죄송합니다. 저의 코드 실행 결과는 아래와 같습니다. 다시 한 번 확인 부탁드립니다!
시각화 프로그램을 써봐도 잘 모르겠어서 시각화 프로그램 사용 결과도 첨부드립니다.
Re: 31.4 연습문제 질문이요!
, 도장_ 관리자님이 작성해당 단원은 연습문제이므로 정답 코드가 제시되어 있습니다.
정답 코드를 보고 문제를 풀이하는 방식을 이해하는 게 더 중요합니다.
결과가 None이 나오는 이유는
is_palindrome(word)로 호출하고 끝나기 때문입니다.
print(is_palindrome('hello'))
print(is_palindrome('level'))
print(is_palindrome('level'))
이 코드를 보면 is_palinedrome()의 호출 결과를 print()로 출력하는 겁니다.
따라서 is_palinedrome() 함수에서는 True나 False를 반환해야 합니다.
그러나 is_palindrome(word)로 재귀호출하는 형태로 끝납니다.
재귀호출한 is_palinedrome(word)의 어딘가에서 반드시 True나 False를 호출하고
끝나야 하지만, 그냥 어떤 값도 반환하지 않고 종료되기 때문에 None이 출력되는 겁니다.
is_palinedrome() 함수를 호출했지만, True/False 반환이 없고, 함수가 종료되었기 때문에 반환값은 None이고, 결과로 None이 출력되는 겁니다.
'level'만 호출하는 코드로 만들어서 살펴보면
level에서 l과 l을 제거하고, eve가 남았을 때 e와 e를 제거하고 v만 남았을때 마지막 호출을 합니다.
line 3을 보면 len(word) == 1은 True입니다. 따라서 return True를 합니다.
그런데 이건 재귀로 짠 겁니다. 일반적인 함수 로직이 아니죠.
재귀라는 건 이전의 호출을 현재 호출에서 사용하는 겁니다.
따라서 최초 호출한 is_palinedrome()의 반환값이 아닙니다.
호출 구조를 봅시다. 재귀로 짰으니까요. 애초에 재귀로 짜면 안 됩니다.
반복문으로 짜는 것을 재귀로 짰기 때문에 일반적이지 않고, 코딩 테스트나 면접이면 탈락하는 코드입니다.
보통은 재귀로 짜도 성능이나 스택 깊이 때문에 비재귀로 다시 바꿔서 제출해야 통과할 수 있는 코딩 테스트가 대부분입니다.
어쨌든 호출 구조를 봅시다.
level -> eve -> v
이렇게 호출 구조가 되어 있습니다. 그리고 v에서는 True를 반환합니다.
len(word) == 1이니까요. 그래서 v에서 리턴하면
이제 호출 구조는
level -> eve가 됩니다.
왼쪽 하단에 step 21과 22를 보세요. step 21은 분명 line 4에 return True였습니다.
step 22는 line 8이고, 다음은 line 9입니다(빨간색 화살표).
is_palinedrome('v')를 호출했고, 이건 반환이 없습니다.
is_palinedrome('v') 단계에서 분명 return True가 실행되었지만, 재귀의 연속이므로
return is_palinedrome('v')로 작성하지 않았으니까 그 return True는 버려집니다.
그게 step 22에서 Return value가 None으로 찍히는 이유입니다.
계속해서 재귀였기 때문에 다음 단계를 실행하면
step 23이 되고, 여전히 line 8입니다. 재귀였으니까 이전 호출로 가죠.
is_palinedrome('eve') 단계에서도 return이 없으니까 Return Value는 None입니다.
그러면 최종적으로 is_palinedrome('level') 단계에서도 None입니다.
첫 번째 'hello' 호출에서는 어떻게 False가 출력되었는가?
첫 번째 호출에서 h와 o이므로 일치하지 않아서 재귀호출 단계에 진입하지 않았고
바로 return False가 실행되었기 때문입니다.
'hello' 대신에 'hellh'로 딱 한 번만 재귀를 탈 수 있게 만들어서 테스트해보세요.
e와 l 단계에서 False이지만, 바로 재귀가 종료되면 Return Value는 None으로 바뀝니다.
step 15에서는 False이지만, step 16에서는 바로 None으로 바뀝니다. 최종 출력도 None입니다.
그러니 처음에 테스트할 때 False, None이 나온다고 해서 False가 코드가 제대로 회문을 판별했기 때문에 나온 게 아닙니다.
재귀로 짜고 싶다면 return is_palinedrome() 형식으로 작성해야 합니다.
안에서 is_palinedrome()으로 호출하면 return이 없기 때문에 안 됩니다.
같은 코드에서 return is_painedrome()으로 바꿔봅니다.
hellh에서 ell 단계이고, False가 됩니다.
return value가 False입니다.
그 다음 단계에서도 Return value가 계승되어서 False입니다. None이 아니라 False가 되었죠?
'level'로 테스트해보세요.
v 단계에서 최종 True입니다. 이전에는 재귀호출이 종료되면 None으로 바뀌었죠.
이제는 return으로 작성했으니 최종 값이 이전 호출로 전달됩니다.
step 22에서도 Return value가 True입니다.
최종적으로 True가 출력됩니다.
다만, 재귀로 문제를 풀면 면접에서는 반드시 비재귀로 다시 작성할 것을 요구받습니다.
따라서 재귀로 작성하면 비재귀로 코드를 변환하는 연습을 해야 합니다.
word를 del로 삭제하지 말고, 슬라이스를 사용하세요.
코드가 훨씬 더 간결해집니다.
비재귀 버전은 연습문제 해답 코드로 제공됩니다.