Recursive Fonksiyonlar

Selamlar iyi akşamlar.

Recursive Fonksiyonlara geldim ve bir hayli zorlandım diyebilirim. Örneğin ilk konu girişinde şu var.

 def azalt(s):
    if len(s) < 1:
        return s
    else:
        print(s)
        return azalt(s[1:])

print(azalt('istihza'))

Şimdi buradaki azalt(s[1:]) kısmını anladım girdiğim kelimeyi yenileyip [1:] den itibaren alıp dura dura
kelimeyi kısaltıyor.

Ancak onun üstündeki print(s) kısmını ve neden len(s) 1 den küçükken s yi döndürdüğünü anlamadım.

Yardımcı olursanız sevinirim.

Soru sorarken sikca dusulen hatalar #1

1 Beğeni

Kusura bakmayın şimdi yaptım düzeltmeyi teşekkür ederim.

3 Beğeni
def azalt(s):
    if len(s) < 1:
        return s
    else:
        print(s)
        return azalt(s[1:])

print(azalt('istihza'))

Anlatayim:

    if len(s) < 1:
        return s

Buradan baslayalim, bu bir edge case. s bir karakter dizisi, len ise aldigi karakter dizisinin uzunlugunu int olarak donduren bir baska fonksiyon. Eger verilen karakter dizisinin uzunlugu 0’dan kucukse karakter dizisini ayni haliyle dondur. (len(s) == 0 da olabilirdi hatta daha iyi olurdu, len negatif deger dondurmuyor)

    else:
        print(s)
        return azalt(s[1:])

En kisa haliyle: Karakter dizisinin uzunlugu 1’den kucuk degilse (1’e esit veya 1’den buyukse) o karakter dizisinin ilk karakterini eksilt (s[1:]). Ve bir karakteri eksiltilmis karakter dizisi ile tekrar ayni fonksiyonu cagir.


Adim adim gidelim:

print(azalt('reo'))

Fonksiyon calisiyor: Gelen karakter dizisi "reo", uzunlugu 3 ve bu 1’den kucuk degil. else’e gec. Karakter dizisini ekrana yazdir: reo. Karakter dizisinin ilk karakterini dusur: "re". Ilk karakteri dusurulmus karakter dizisiyle fonksiyonu tekrar cagir ve sonucu dondur:

Fonksiyona gelen karakter dizisi: "re". Uzunlugu 2, 1’den kucuk degil, else’e gec. Karakter dizisini ekrana yazdir: re. Ilk karakteri at ve fonksiyonu tekrar cagir ve sonucu dondur: "r".

Fonksiyona gelen karakter dizisi: "r". Uzunlugu 1, 1’den kucuk degil, else’e gec. Ekrana yazdir: r. Ilk karakteri at ve fonksiyonu cagir ve sonucu dondur: "".

Gelen: "", uzunluk 0, 1’den kucuk, karakter dizisini ayni haliyle dondur: ".

Eger karakter dizisinin uzunlugu 0 oldugunda fonksiyonu durduran bir kosul eklemeseydik recursion asla durmayacakti, edge case bu ise yariyor. Fonksiyon defalarca calisti, ulasmasi gereken noktaya ulasti ve durdu.

Ayni seyi imperatif yontemle de yapabilirdik:

s = "reo"
while s != 0:
    print(s)
    s = s[1:]
2 Beğeni

Simdi goruyorum ki burasi anlasilmis. Neyse, belki baskasinin isine yarar anlattiklarim :slight_smile:

print’in oradaki tek amaci neler oldugunu gorebilmek. Normalde recursive fonksiyonlar bu sekilde islemez. Gercek bir recursion ornegine ihtiyac var:

def recur_fibo(n):
   if n <= 1:
       return n
   else:
       return recur_fibo(n-1) + recur_fibo(n-2)

O da yukarida bahsettigim gibi, bir edge case.

3 Beğeni

Mükemmelsiniz. Emek verip yardımcı olduğunuz için çok teşekkür ederim. Anlamış oldum.

Bir de şunu sormak istiyorum bu konu veya bu yöntem gerçekten işe yarıyor mu ? Dediğiniz gibi while döngüsü ile yapmak daha kolay. Bu konu sadece bir alternatifmidir yoksa ileride gerekliliği zorunlu bir konumu.

1 Beğeni

Neden yaramasın?

Bu konuda bir listenin alt listelerinin sayısının nasıl bulunabileceği ile alakalı bir soru sorulmuştu, bunun için bir recursive function yazmıştım mesela.

1 Beğeni

Elbette. Fonksiyonel programlama apayri bir programlama paradigmasi ve tamamen recursion ustune kurulu. Dongu kullanarak yapabildiginiz her seyi recursion kullanarak da yapabilirsiniz. Purely Functional Programming language denilen tamamen fonksiyonel diller var, Haskell gibi:

fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

Onlarca farkli fibonacci kodu: The Fibonacci sequence - HaskellWiki

Hayir, oyle bir sey demedim. Recursion cozum icin farkli yontemlerden biri, loop kullanmaya alternatif ve yukarida gosterdigim gibi tamamen onu hedef alan bir paradigma ve diller var.

Kitaptaki ornek konuyu anlatmak icin verilmis bir ornek, normalde recursive fonksiyonlar o sekilde calismaz.

Ileride ne yapacagini bagli, ogrenmekten zarar gelmez. Gun gelir merak edip farkli bir dil ogrenmek istersin. Python’da kullanmak opsiyonel.

1 Beğeni

Evet, yariyor ve hayir, her zaman degil.

Genel olarak butun loop’lar recursive fonksiyonlara, butun recursive fonksiyonlar loop’lara cevrilebiliyor.

Recursive fonksiyon yazmanin daha okunabilir, daha anlasilir oldugu durumlar var. Buyuk bir problemin cozumunun kucuk problemler uzerine insa edildigi durumlar mesela.

Bir listenin permutasyonlarini, kombinasyonlarini veya alt kumelerini olusturmak iyi bir ornek olabilir. Iki sekilde de yazmayi denemek lazim.

1 Beğeni

Base case :slight_smile:
(Digeri recursive case)

Aslinda su konularda yazilanlari duzenleyip ufak ufak bir kitap haline mi getirsek…

Kesinlikle. Aslinda bir pull request acilabilir…

Yeri gelmisken: Edge case, normal kullanimda karsilasilmayan, hatta cogu zaman fonksiyonlarin handle etmeyi unuttugu veya onemsemedigi durumlar. Mesela “nokta dikdortgenin icinde mi” fonksiyonu yazdigimizda noktanin tam kenarda olmasi durumu. (Ismini de buradan aliyor olmasi lazim bu arada)

Iki edge case’in birlestigi nokta da corner case. Tanim geregi cok nadir karsilasilan ve cok daha fazla kodun handle etmedigi, onemsemedigi durumlar.

2 Beğeni