Recursive functions mantığını anlamadım

Merhabalar, recursive fonsiyonlarda mantığını anlayamadığım bir nokta var. Yardımcı olursanız sevinirim.

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

Mesela yukarıda belirttiğim kodun çıktısı
istihza
stihza
tihza… diye gidiyor ancak burda kelimenin harf sayısını döngünün her seferinde azaltmamız gerektiğini yazdığımız bir satır yok. ilk harfi her seferinde bir eksilteceğimizi nasıl belirledik.

def factorial(n):
   if n == 0 or n==1:
        return 1

   return n * factorial(n-1)

sonuc=factorial(5)
print(sonuc)

keza burda da faktoriyel işleminde sayıyı bir azaltmasını istediğimiz satır yok.
Bu işlemlerin mantığını ve çok yormazsam sizi kodda adım adım hangi işlemin/sorgunun yapıldığını söyleyebilirseniz sevinirim. Şimdiden teşekkürler

Merhaba, hoş geldiniz.

Aslında fonksiyonun kendisini return ettiği sırada fonksiyonun aldığı argümanda azaltma işlemini uyguluyoruz. return azalt(s[1:]) ifadesinde s’nin tamamını değil, 1. indisten itibaren olan dilimini argüman olarak veriyoruz. Aynı şekilde factorial foksiyonunda da fonksiyon kendi kendisini çağırırken n parametresine verilen değer azaltılıyor. return n * factorial(n-1) ifadesinde, fonksiyonun her özyineleme aşamasında, n, 1 birim azaltılıyor.

2 Beğeni

Yukardaki azalt fonksiyonundaki ilk satırda önce s argümanından gelen değerin uzunluğunun 1’den küçük olup olmadığına bakılıyor. Şayet küçükse, return s ifadesi ile de s’in son hali geri döndürülüyor. s’in son hali diyorum çünkü bu fonksiyonda s sürekli değişen bir yapıda. s’in alacağı son değer boş bir str verisi yani "" olacaktır.

Şayet s’in uzunluğu 1’den büyükse, ekrana s yazdırılır, sonra da azalt fonksiyonu, kendisine argüman olarak s yerine s[1:] verilerek çağrılır.

s = "istihza"
print(s)
print(s[1:])

Özyinelemenin ilk adımında s argümanının alacağı değer s[1:] olur bunun değeri de stihza. İkinci adımda s[1:] ifadesi tihza olur. Yani fonksiyonu ilk çağrırken ona s isminde bir argüman verdiniz. Aynı değeri, sadece ilk sırasındaki elemanı almadan fonksiyona tekrar argüman olarak veriyorsunuz ve fonksiyonu çağırıyorsunuz. Dolayısıyla elinizdeki argümanların değişen durumlarına göre özyinelemeyi yapıyorsunuz. if len(s) < 1 ifadesiyle de zaten s’in uzunluğunun azalacağını bildiğiniz için bu durumda ne yapılması gerektiğini tanımlamış oluyorsunuz. Genelde bu durumda fonksiyonun işi de biter.

Yukardaki factorial fonksiyonunun ilk satırında n’in 0’a veya 1’e eşit olup olmadığı sorgulanır. Eşitse 1 döndürülür. Değilse, n * factorial(n - 1) ifadesi döner.

Şimdi burada neden n’i bir fonksiyonla çarpıp geri döndürüyoruz diye düşünmüş olabilirsiniz. Bu bahsettiğim ifade hem aynı anda n’in aldığı değeri döndürüyor hem de kendisini n’in değerini 1 azaltarak döndürüyor. Yani:

return n * factorial(n - 1)

Yukardaki ifadede factorial(n - 1) fonksiyonu neyi geri döndüyor? (n - 1) * factorial(n - 2) ifadesini döndürmez mi?

Matematikten hatırlayalım:

f(x) = x * f(x - 1)
f(x - 1) = (x - 1) * f(x - 2)

O halde (n - 1) * factorial(n - 2) ifadesini alıp, factorial(n - 1) gördüğümüz yere yazalım.

return n * (n - 1) * factorial(n - 2)

Peki, aynı şekilde factorial(n - 2)'nin de ne döndüreceğine bakalım.

(n - 2) * factorial(n - 3)

O zaman factorial(n - 2) gördüğüm yere de yukardaki ifadeyi yazabilirim.

return n * (n - 1) * (n - 2) * factorial(n - 3)

Bu işlemler, yazdığınız koda göre n = 1 veya n = 0 durumuna kadar yapılacaktır. n = 1 durumunda elimizde ne olacak? return 1. Daha önceden return edilen n değerlerimiz vardı, yukarda göstermiştim. O halde son olarak dönecek olan değer şöyle bir değer olacaktır.

return n * (n - 1) * (n - 2) * ... * 1

Umarım anlatabilmişimdir.

2 Beğeni

Değerli cevaplarınız için teşekkür ederim öncelikle. İki soru daha kafama takıldı.
1- İlk olarak tam metin olarak " istihza " yı yazdırma işlemini hangi satırdaki kod ile yaptık, mantığını henüz anlayamadığım için ben düz olarak şu şekilde sordum kendime eğer [1:] ekliyorsak tam metin neden yazdırıldı ilk satıra?
2- her döngüde 1 harf azaltarak ilerlediğimizde if’li koşul gerçekleşip yani hiçbir harf kalmayıp len uzunluk 1in altına 0’a düştüğünde bu kodu sonsuz döngüye sokmayan nedir ?
Bir yandan kendimde kod üzerinde oynamalar yaparak bu soruya cevap arıyorum ama yetersiz kalıyorum, ve işleyiş mantığını tamamen anlamak için bu kadar sorgulayıcı oluyorum, emeğiniz için teşekkür ederim şimdiden

        print(s)

eğer uzunluk 0 sa return azalt(s[1:]) bu kısım devreye girmiyor ve bir daha fonksiyon çalışmıyor.

1 Beğeni

Rekürsif fonksiyonları matruşka bebekler gibi düşün. Baştan büyük bebeği görüyorsun, sonra onu her açtığında aynı bebeğin küçüğünü görüyorsun.

Burada da çalışan aynı fonksiyon ama gönderdiği değer farklı olduğu için yazdığı da farklı oluyor.

Mesela fibonacci serisini de ben ekleyeyim.

def fibo(x):
    if x==1 or x==2: #x in değeri 1 veya 2 ise 1 döndür (fibonacci dizisinin ilk iki elemanı)
        return 1
    else:
        return fibo(x-1)+fibo(x-2) #değilse x ten 1 önceki ve iki önceki elemanları bul ve topla

print(fibo(10)) #fibonacci dizisinin 10. elemanını yazdır
1 Beğeni