• 목록
  • 아래로
  • 위로
  • 13
  • NoYeah
  • 조회 수 564

파이썬공부를 하던 중 재귀 함수에 대해 공부하다 어떤 과정으로 프로세스가 이루어지는지 잘 이해가 되지 않아 질문드립니다.


일단, 특정수가 홀수인지 짝수 인지 확인하는 함수입니다.

조금 더 효율적으로 작성할 수도 있지만 재귀함수를 공부하는 도중에 작성한 코드이기 때문에 다른 형태의 코드에 대해서는 감사하지만 따로 알려주시지 않아도 됩니다.


예를 들어 is_odd(17) 을 확인했을 때 True 를 반환하고 is_odd(18)을 확인할 때는 False 가 나오도록 합니다.

반면, is_even(17)을 입력하면 False를, is_even(18)을 입력하면 True를 반환합니다.


def is_even(x):
    if x==0:
        return True
    else:
        return is_odd(x-1)

def is_odd(x):
    return not is_even(x)



여기에 아래처럼 테스트 해보면 아래와 같은 결과가 나옵니다.


print(is_odd(19))
True

print(is_even(19))
False



Sololearn을 통해 공부하던 중 is_even(19)를 입력했을 때 False 가 나오는 과정을 상세하게 설명을 듣고자 합니다.


제가 이해한 바로는

is_even(19)를 입력하면 19가 0이 아니기 때문에 is_odd(18)을 리턴시키고

is_odd(18)에서는 not is_even(18)을 반환하는 것으로 이해했습니다.


not 구문이 들어가서 어떻게 해석(이해)을 해야하는지 궁금합니다.

작성자
NoYeah 80 Lv. (39%) 517120/524880EXP

신나는 도박사이트!

 

https://studyforus.com

댓글 13

title: 황금 서버 (30일)humit
profile image
+1

is_even(19)을 입력했을 때 19가 0이 아니기 때문에 else 부분에 있는 is_odd(18)이 실행해서 해당 값을 반환합니다.
그리고 is_odd(18)에서는 is_even(18)을 실행해서 나온 결과에 not 연산자를 적용하게 됩니다.
is_even(18)은 다시 18이 0이 아니기 때문에 else 부분에 있는 is_odd(17)을 실행해서 해당 값을 반환합니다. 이것을 계속 반복해서 is_even에 0이 호출될 때까지 실행합니다.
 

어떤 식으로 함수가 호출되는지 알고 싶으시다면 아래와 같이 print 함수를 쓰는 것도 괜찮습니다.


def is_even(x):
    print('call is_even({})'.format(x))
    if x==0:
        return True
    else:
        return is_odd(x-1)
 
def is_odd(x):
    print('call is_odd({})'.format(x))
    return not is_even(x)

print(is_even(19))



comment menu
2019.02.09. 23:48

신고

"humit님의 댓글"

이 댓글을 신고 하시겠습니까?

NoYeah 작성자 → humit
profile image

한번 이대로 실행해보겠습니다. 감사합니다!

comment menu
2019.02.10. 03:18

신고

"NoYeah님의 댓글"

이 댓글을 신고 하시겠습니까?

이니스프리
profile image
+1

이건 파이썬 자체의 문제가 아니라 코딩 차원의 문제인 것 같군요 ^-^


재귀함수는 너무 난해해서 저도 텍스트북이나 수업을 통해서 배우기만 하고 실제로 사용해본 기억은 거의 없네요 ㅠㅠ

(저처럼 날림으로 파이썬을 공부한 사람의 특징인 것 같습니다 ㅜㅜ)



우선 not은 boolean 연산자로서 기존값의 반대값을 취합니다.


True에 대해 False를, False에 대해 True를 취하게 됩니다.


즉 논리학에서의 '~'와 동일한 의미입니다.


올려주신 스크립트에서는 is_even(x)값에 not이 붙으면 반대의  boolean 값을 취하게 됩니다.



19는 숫자가 크니 작은 숫자로 예를 들어 계산과정을 설명드릴게요.


x가 1씩 감소하면서 0이 될 때까지 not이 몇 번 붙느냐에 따라서 최종 boolean 값이 결정됩니다.


이건 파이썬이 아니라 논리학의 측면에서 접근하시면 수월합니다 :)


is_even(3)

is_odd(2) 

not is_even(2)

not is_odd(1)

not (not is_even(1))

not(not is_odd(0))

not(not(not is_even(0)))

not(not(not True)))

not(not False)

not True

False

is_even(2)

is_odd(1)

not is_even(1)

not is_odd(0)

not(not is_even(0))

not(not True)

not False

True



괄호 때문에 위와 같이 정석적(?)으로 정리하긴 했지만 


기계가 아닌 사람이 머리 속에서 계산을 할 때에는 not과 not이 만나면 지워진다고 생각하시면 보다 간단합니다 ㅎㅎ


위에 정리한 것처럼 is_even() 함수에 어떤 정수를 집어넣었을 때 


최종적으로 False가 도출되면 not이 홀수번 붙고, True가 도출되면 not이 짝수번 붙는다고 생각하시면 되겠네요.



대략 다음과 같은 방법으로 함수에서 변수를 찍어보시면 이해에 도움이 되실거에요~!


def is_even(x):
    if x==0:
        return True
    else:
        print('even' + str(x))
        return is_odd(x-1)
 
def is_odd(x):
    print('odd' + str(x))
    return not is_even(x)



+) 

답변을 작성하는 사이에 humit 님께서 이미 저보다 정확한 답변을 달아주셨군요 ^^

humit 님께서 올려주신 스크립트처럼 else가 아니라 is_even 함수의 첫 단계에서 값을 찍어보는 것이 좋을 것 같네요.


++)

외람된 말씀이지만... 재귀함수를 공부하다보면 프로그래밍 공부가 너무 어려워서 재미없지 않으신지요?? ㄷㄷ

이 파트가 저만 어렵다고 생각하는 것인지도 모르겠네요 ㅠㅠ



+++)

재귀함수와 관련은 없지만 제 허접한 수준에서 그나마 파이썬스러운 스크립트를 작성해보면 다음과 같습니다.


def even_or_odd(number):
    print("even" if number % 2 == 0 else "odd")



comment menu
2019.02.09. 23:56

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

NoYeah 작성자 → 이니스프리
profile image

is_even(3)

is_odd(2)

not is_even(2)

not is_odd(1)

not (not is_even(1))

not(not is_odd(0))

not(not(not is_even(0)))

not(not(not True)))

not(not False)

not True

False

 

 

is_even(2)

is_odd(1)

not is_even(1)

not is_odd(0)

not(not is_even(0))

not(not True)

not False

True

 

이 부분으로 파악했습니다.

결국엔 not을 붙인채로 is_even 함수를 계속 사용하는 거였군요.

 

이제 이해되었습니다.

 

not 인채로 is_even 안의 함수 내용을 살펴보다 보니 어떻게 해석해야 하는 건가 했는데 확실히 이해되었습니다. 감사합니다!!

 

그리고 재귀함수는 여러가지 상황을 더 자유롭게 할 수 있는 흥미있는 내용인것 같습니다.

다행이 "타의"에 의해 (취업이나 학과 과정) 공부하는 것이 아닌 "흥미"를 위한 공부여서 그런지 하나하나 배우는게 재밌네요~

comment menu
2019.02.10. 03:21

신고

"NoYeah님의 댓글"

이 댓글을 신고 하시겠습니까?

이니스프리 → NoYeah
profile image

오오~ 제가 개떡 같이 설명을 드렸는데 다행히 찰떡 같이 이해하셔서 다행이네요 ^-^

말씀하신대로 boolean 값에 not이 하나씩 붙으면서 x==0일 때까지 재귀함수가 계속 돈다고 생각하시면 되어요.

일반적인 정수나 문자열 변수가 아니라 boolean 변수이기 때문에 다소 특이한 경우라고 볼 수 있겠네요.

저는 재귀함수가 너무 어려워서 응용적인 측면에서는 사실상 포기를 했는데 이 파트가 재미있으시다니 다행이네요 :)

(재귀함수도 어렵고 논리학도 어렵네요 ㅠㅠ)

 

그리고 말씀드린대로 이해가 안 되는 스크립트에서는 변수값을 찍어보는 것이 이해에 도움이 되더군요.

이 스크립트 같은 경우에도 대입하는 정수값이 5 이상으로 커지면 인간의 머리로 boolean 값을 계산하는 것이 골치가 아파서요 ㄷㄷ

 

그럼 감기 조심하시고 즐거운 주말 되세요!

comment menu
2019.02.10. 09:54

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

NoYeah 작성자 → 이니스프리
profile image

중학교??고등학교?? 수학때 배운 명제 파트가 생각나네요.

 

p=>q 인 명제와 그 대우인 ~q=>~p 가 서로 성립한다. 했던 그런 내용이요 ㅋㅋ

comment menu
2019.02.10. 11:00

신고

"NoYeah님의 댓글"

이 댓글을 신고 하시겠습니까?

이니스프리 → NoYeah
profile image

그러게요~! 제 기억이 맞다면 교과서상으로는 고1에 수록되어 있던 것 같고 많은 학생들이 중2, 3 정도에 공부했던 것 같네요 ㅎㅎ

아마도 p -> q와 그 대우인 ~q -> ~p는 논리적 동치라는 내용이었죠 ^^

증명을 어떻게 하는지는 기억이 안 나네요 ㅠㅠ

comment menu
2019.02.10. 12:42

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

NoYeah 작성자 → 이니스프리
profile image

역 이 대우 중에 대우 명제로 기억하네요. ㅎㅎ

comment menu
2019.02.10. 14:26

신고

"NoYeah님의 댓글"

이 댓글을 신고 하시겠습니까?

abnoeh → 이니스프리
profile image

p->q일때 ~q지만 p인 경우가 있다고 하면 p->q가 거짓이 되죠?

comment menu
2019.02.10. 19:12

신고

"abnoeh님의 댓글"

이 댓글을 신고 하시겠습니까?

NoYeah 작성자 → abnoeh
profile image

이미 p->q 인 참인 명제에서 ~q -> p 가 될 수 있는 명제가 없습니다.

 

q의 진리집합이 p의 진리 집합 보다 크고 p집합은 q집합의 부분집합이 되기 때문에 q집합의 여집합은 p집합의 부분집합이 될 수없습니다.

 

만약 전체 명제를 u라고 하면 p, q , u 집합이 모두 같다면 가능하긴 하겠네요. 그땐 p->q인 명제는 거짓이 될 수 없겠지요.

 

 

comment menu
2019.02.10. 19:23

신고

"NoYeah님의 댓글"

이 댓글을 신고 하시겠습니까?

abnoeh → NoYeah
profile image

그니까 귀류법으로 (p->q)->(~q->~p)가 증명되죠

comment menu
2019.02.10. 19:29

신고

"abnoeh님의 댓글"

이 댓글을 신고 하시겠습니까?

NoYeah 작성자 → abnoeh
profile image

아아 대우 명제의 증명을 이야기하신거군요.

comment menu
2019.02.10. 20:06

신고

"NoYeah님의 댓글"

이 댓글을 신고 하시겠습니까?

라엘
profile image

으앗 어려웡

comment menu
2019.02.10. 23:14

신고

"라엘님의 댓글"

이 댓글을 신고 하시겠습니까?

권한이 없습니다.
번호 제목 글쓴이 날짜 조회 수
공지 시스템 점검 작업 완료 안내 10 마스터 24.09.05.16:25 2101
공지 [중요] 호스팅 만료와 관련하여 일부 수칙이 변경됩니다. 4 마스터 23.01.14.02:23 8905
공지 [필독] 질문하는 방법 17 마스터 18.02.23.03:09 4871
546 디시인사이드 푸쉬알림 앱 추천 부탁드립니다 ^^ 3 이니스프리 19.04.18.23:35 1590
545 프로세서 간의 성능 비교에 대해 질문 드립니다 ^^ 4 이니스프리 19.04.17.18:31 270
544 사파리브라우저 mp3파일 재생관련 문의드립니다. 11 자뻑보이 19.04.15.15:26 685
543 라떼판다 전원 설계가 막막해요 ㅠㅠ 2 나는야초보 19.04.10.22:52 966
542 모니터의 피봇(pivot)과 관련하여 질문 드립니다 8 이니스프리 19.04.10.13:59 292
541 드롭다운 메뉴의 아이콘에 배경색이 칠해지지 않아요 6 image 국내산라이츄 19.04.07.03:29 384
540 Linux 시스템 보안에서 실무 등에서는 어떤 보안 솔류숀을 사용하는지 궁금해요 1 Seia 19.04.05.23:00 353
539 맥북의 팬리스 여부가 정리된 웹페이지를 추천 부탁드립니다 ^^ 4 이니스프리 19.03.31.10:49 345
538 태블릿을 컴퓨터 키보드로 사용할 수 있는 앱 추천 부탁드립니다. 이니스프리 19.03.29.18:31 284
537 스포어 메일 연결해서 쓰시는분 있으신가요? 6 샹키 19.03.22.17:43 437
536 공유폴더가 안됩니다 원인을 알고싶습니다.. 4 image calm 19.03.19.20:12 473
535 실시간 검색어 파싱에 ajax를 적용했는데 캐싱을 할 수 있는 방법이 어떤 것이 있을지 여쭤봅니다 4 image 이니스프리 19.03.12.12:42 604
534 Ping 유무 html로 표현 6 image 사나이 19.03.10.22:08 750
533 흠.. 여기가 빠른 답변이 가능할까요? 3 워시퍼 19.02.26.15:21 335
532 앱에서의 MIT라이센스 표시 관련하여 질문합니다. 4 title: 에그joyful 19.02.19.15:18 547
531 그누보드 5 설치 오류 도와주세요 3 image 김호창 19.02.15.16:19 2300
530 TXT레코드 관련 도와주세[요! 7 image AA 19.02.14.23:21 317
529 라이믹스 ckeditor4 2 image title: 크롬NUBE 19.02.13.22:41 400
528 SQL문을 PHP에서 실행시켰는데 안되네요 7 260578 19.02.11.15:59 414
[Python 질문] 재귀함수의 알고리즘이 잘 이해가 되지 않습니다. 13 NoYeah 19.02.09.23:21 564