Fonksiyonlara giriş

İlk beş haftada programlarımız giderek büyüdü: değişkenler kullandık, koşullar kurduk ve döngüler yazdık. Kod büyüdükçe aynı işlemi tekrar tekrar yazmaya başlarız. Bir hatayı birden fazla yerde düzeltmek gerekir, programın hangi parçasının hangi işi yaptığını anlamak da zorlaşır.

print() ve input() gibi Python’ın hazır fonksiyonlarını zaten kullanıyorsunuz. Fonksiyon, bir işi yapan ve adıyla çalıştırılan kod parçasıdır. Bu hafta kendi fonksiyonlarımızı yazıp problemi küçük, adlandırılmış parçalara ayıracağız. def söz dizimini öğrenirken bir fonksiyonun hangi bilgiyi aldığına, hangi işi yaptığına ve sonucu kime verdiğine de bakacağız.

Bu sayfadaki kod hücreleri kendiliğinden çalışmaz. Her hücrede önce çıktıyı tahmin edin, sonra Run Code düğmesine basın. Kodu değiştirip yeniden çalıştırabilir, Start Over ile ilk hâline döndürebilirsiniz.

Bu bölümün kapsamı

NotSınavda sorulur
  • Fonksiyon tanımı ile çağrısının ayrımı
  • Parametre ile argüman ayrımı ve argüman sayısı uyuşmazlığı
  • print() ile return farkı
  • return çalıştığında fonksiyonun sona ermesi
  • Değer döndürmeyen fonksiyonun örtük None döndürmesi
  • Dönüş değerini başka ifadelerde kullanma
  • Problemi küçük fonksiyonlara ayırmanın gerekçesi
  • Değişken sayıda argüman (*args, **kwargs)
  • Fonksiyon içinde fonksiyon tanımlama

Bu başlıklar konunun devamıdır. İleride karşınıza çıkar, ama bu derste ezberlemeniz beklenmiyor.

Fonksiyon neden kullanılır?

Bir dikdörtgenin alanını birkaç yerde hesapladığımızı düşünelim:

genislik1 = 4
yukseklik1 = 6
alan1 = genislik1 * yukseklik1

genislik2 = 7
yukseklik2 = 3
alan2 = genislik2 * yukseklik2

Aynı hesabı tekrar yazmak yerine ona bir ad verip bir fonksiyon yapabiliriz. Sonra aynı hesabı farklı değerlerle çalıştırırız. Hücre hangi iki satırı yazar?

Burada fonksiyonun iki yararı var:

  • Hesaba ne yaptığını anlatan bir ad verir.
  • Aynı hesap, yeniden yazılmadan farklı değerlerle kullanılabilir.

def, return ve parantezin içindeki adları bölümün geri kalanında tek tek göreceğiz.

İpucu

Bir kod parçasını fonksiyona dönüştürüp dönüştürmeyeceğinize karar verirken yalnızca “bu kod tekrar ediyor mu?” diye sormayın. “Bu parçanın tek ve açık bir işi var mı?” diye de sorun.

Fonksiyon tanımı ve çağrısı

Bir fonksiyonun tanımı def ile başlar:

def selamla():
    print("Merhaba")

def satırının altındaki girintili satırlara fonksiyonun gövdesi denir. Bu kod fonksiyonu tanımlar, yani selamla adını bu gövdeye bağlar, ama gövdeyi henüz çalıştırmaz. Gövdeyi çalıştırmak için fonksiyonu adıyla ve parantezle çağırırız:

selamla()

Aşağıdaki program kaç satır yazar, satırların sırası ne olur?

Fonksiyon tanımı programın başında yer alsa da gövdesi yalnızca mesaj_yaz() çağrısı yapıldığında çalışır.

Parantezi unutursanız

Bu hücrede selamla iki kez geçiyor, ama ikisinde de addan sonra parantez yok. Hücre Merhaba yazar mı?

Merhaba yazılmaz. Parantezsiz selamla satırı fonksiyonu çağırmaz, yalnız adını anar ve hiçbir şey yapmaz. print(selamla) ise fonksiyonun kendisini <function selamla at 0x...> gibi bir satırla yazar. Gövdeyi addan sonraki parantez çalıştırır: selamla().

Çağrı tanımdan önce gelirse

Bu kez çağrı tanımdan önce yazılmış. Hücre çalışır mı?

Python dosyayı yukarıdan aşağıya satır satır çalıştırır. İlk satıra geldiğinde def satırı henüz çalışmadığı için selamla adı tanımlı değildir. Python bu durumda NameError hatası verir. Çağrıyı tanımın altına taşıyıp yeniden deneyin.

Fonksiyonun dosyanın herhangi bir yerinde yazılı olması yetmez. Program çağrı satırına geldiği anda ad tanımlı olmalıdır. Bu yüzden şimdilik fonksiyon tanımlarını onları kullanan ana koddan önce yazın. Bu düzen kodu okumayı da kolaylaştırır.

Parametre ve argüman

Fonksiyonun farklı değerlerle çalışabilmesi için tanımdaki parantezin içine bir ad yazarız. Bu ada parametre denir:

def selamla(ad):
    print("Merhaba", ad)

Burada ad, fonksiyon tanımındaki parametredir. Fonksiyonu şöyle çağırabiliriz:

selamla("Deniz")

Çağrıda parantezin içine yazılan "Deniz" ise argümandır: parametreye o çağrıda verilen değer. Bir form düşünün: formdaki boş kutular parametredir, formu dolduran kişinin kutulara yazdığı değerler argümandır.

Tanım:  def selamla(ad):
                     ↑
                 parametre

Çağrı: selamla("Deniz")
               ↑
            argüman

Bir fonksiyon birden fazla parametre alabilir. Argümanlar parametrelere sırayla eşlenir: ilk argüman ilk parametreye, ikinci argüman ikinci parametreye gider. Aşağıdaki return satırı hesaplanan değeri çağrının yerine koyar, ayrıntısına birazdan bakacağız. Hücre hangi iki satırı yazar?

Argümanların sırası

Bu çağrıda ad ile şehir yer değiştirmiş. Hücre ne yazar? Python sıranın yanlış olduğunu fark eder mi?

Hücre hata vermez, Ad: Samsun Şehir: Deniz yazar. Python argümanları yazıldıkları sırayla eşler: ilk değer ad, ikinci değer sehir olur. Değerin ne anlama geldiğine bakmaz. Sırayı doğru vermek çağrıyı yazanın işidir.

Eksik argümanla çağrı

toplam_fiyat iki parametre bekliyor. Bu çağrıda yalnız bir argüman var. Hücre ne yazar?

Python eksik argümanı kendiliğinden tamamlamaz, boş kutuyu 0 da saymaz. Eksik ya da fazla argümanla yapılan çağrı TypeError hatası verir. Eksik argümanda mesajda “missing” (eksik) sözcüğü geçer. Fazla argümanı görmek için çağrıyı toplam_fiyat(25, 4, 3) yapıp yeniden çalıştırın. Bu kez mesaj “takes 2 positional arguments but 3 were given” (iki argüman alır ama üç verildi) gibi bir cümledir.

İpucu

Bir fonksiyon çağrısında TypeError gördüğünüzde önce şunu kontrol edin: Fonksiyon kaç parametre tanımlıyor, ben kaç argüman verdim?

return: fonksiyonun döndürdüğü değer

Çoğu zaman fonksiyonun hesapladığı değeri ekrana yazmak yerine programın başka bir yerinde kullanmak isteriz. Hücre ne yazar?

return, hesaplanan değeri fonksiyonun çağrıldığı yere geri gönderir. Bu değere fonksiyonun dönüş değeri denir. Burada kare(5) çağrısının dönüş değeri sonuc değişkenine atanır.

Fonksiyon tanımı, çağrı, parametre, argüman ve dönüş değeri arasındaki ilişki.

Fonksiyon çağrı akışı

Aşağıdaki iki fonksiyon aynı toplamı hesaplıyor. Biri sonucu ekrana yazıyor, öteki döndürüyor. Hücre ne yazar? Sonra dondurerek_topla yerine yazdirarak_topla yazıp yeniden çalıştırın.

dondurerek_topla(10, 20) çağrısı 30 döndürür. ara_toplam 30 olur, genel_toplam 35 olur ve 35 yazılır.

yazdirarak_topla ile önce 30 yazılır: bu, fonksiyonun içindeki print()’in işidir. Fonksiyonda return olmadığı için ara_toplam None olur. ara_toplam + 5 hesabı None + 5 olur ve TypeError verir. Ekranda görünen 30, programın geri kalanının eline geçmedi.

Önemli

print() değeri ekranda kullanıcıya gösterir. return ise değeri fonksiyonu çağıran koda geri verir. Çağıran kod bu değeri bir değişkende tutabilir ya da başka bir hesapta kullanabilir.

print ile ekrana yazdırma ve return ile çağırana değer döndürme arasındaki fark.

print ve return farkı

return olmayan fonksiyonun dönüş değeri

Bu fonksiyonda return yok. Hücre kaç satır yazar, ikinci satırda ne görünür?

İki satır yazılır: 80.0 ve Dönen değer: None. İlk satırı fonksiyonun içindeki print() yazdırır. İkinci satırdaki None ise fonksiyonun dönüş değeridir.

Fonksiyonun sonuna gelindiğinde hiçbir return satırı çalışmadıysa fonksiyon yine de bir değer döndürür: None. Kodda yazılmadığı hâlde Python’ın kendiliğinden döndürdüğü bu değere örtük dönüş değeri denir. None, “bu fonksiyon işe yarar bir sonuç döndürmedi” demektir.

Bu yüzden ekrana yazan fonksiyonla değer döndüren fonksiyonu birbirinden ayırın:

def ortalama_yazdir(a, b):
    print((a + b) / 2)

def ortalama_hesapla(a, b):
    return (a + b) / 2

İkinci fonksiyonun sonucu başka bir hesapta kullanılabilir.

Not

None kendi başına bir değerdir: bir değişkene atanabilir, print() onu None diye yazar. İlerleyen haftalarda bazı fonksiyonların “sonuç yok” demek için bilerek None döndürdüğünü de göreceğiz.

Tahmin et: return sonrasında ne olur?

Aşağıdaki programın çıktısını ve fonksiyonun dönüş değerini tahmin edin:

return çalıştığında fonksiyon sona erer. Bu nedenle return satırından sonraki print() çağrısına ulaşılmaz.

Alıştırma: eksik dönüş değerini tamamlayın

Aşağıdaki fonksiyon iki sınav notunun ortalamasını hesaplamalı, ama şu anda sonucu döndürmüyor.

Fonksiyonun 80.0 değerini döndürmesini sağlayın.

sonuc değişkeni zaten hesaplandı. Fonksiyonun sonuna return sonuc ekleyebilirsiniz.

def ortalama(not1, not2):
    sonuc = (not1 + not2) / 2
    return sonuc

print(ortalama(70, 90))

Fonksiyonun sonucunu başka bir ifadede kullanmak

Dönüş değerini herhangi bir değer gibi kullanabilirsiniz. Hücre ne yazar?

Fonksiyon çağrısı doğrudan bir ifadenin içinde de yer alabilir:

odenecek = urun_tutari + kdv_hesapla(urun_tutari, 0.20)

Ara değerin bir anlamı varsa (buradaki kdv gibi) onu ayrı bir değişkende tutmak kodu çoğu zaman daha okunur yapar.

Alıştırma: çevre fonksiyonunu yazın

Bir dikdörtgenin çevresini hesaplayan cevre_hesapla fonksiyonunu tamamlayın. Çevre, iki kenarın toplamının iki katıdır.

Beklenen sonuç 26’dır.

Fonksiyonun dönüş değeri 2 * (genislik + yukseklik) olmalıdır. Parantezi unutursanız önce çarpma yapılır.

def cevre_hesapla(genislik, yukseklik):
    return 2 * (genislik + yukseklik)

print(cevre_hesapla(8, 5))

Bir problemi küçük fonksiyonlara ayırmak

Fonksiyonlarla tekrarı azaltmanın yanında büyük bir problemi küçük adımlara da bölebiliriz. Örneğin bir alışveriş tutarı için önce indirimi bulalım, sonra kalan tutara KDV ekleyelim. Hücre ne yazar?

Burada her fonksiyonun işi tek cümleyle açıklanabilir:

  • indirim_hesapla: tutardan düşülecek indirimi bulur.
  • kdv_ekle: tutara yüzde 20 KDV ekler.

kdv_ekle çağrısında argüman bir hesap: urunler_toplami - indirim. Python önce bu hesabı yapar, çıkan 900.0 değerini tutar parametresine verir.

Sonuç yanlış çıkarsa sorunun hangi adımda olduğunu bulmak da kolaylaşır: indirim ve KDV fonksiyonlarını ayrı ayrı deneyebilirsiniz.

Fonksiyonun içindeki değişkenler

Fonksiyonun içinde oluşturulan değişkene yerel değişken denir. Ortalama alıştırmasındaki sonuc böyle bir değişkendir: fonksiyon her çağrıldığında yeniden oluşur. Ara hesapları fonksiyonun içinde bırakın, çağıran kodun kullanacağı sonucu return ile döndürün. Dışarıdaki kod sonuc adını kullanmaya çalışırsa ne olduğunu 7. bölümde deneyeceğiz.

Hepsi bir arada: kasadaki indirim kartı

Bir mağazada kasiyerler indirimli fiyatı her satışta elle hesaplıyor. Hesap bir karta yazılırsa her kasiyer aynı adımları izler. Kartın bir adı ve iki boş kutusu var: ürünün fiyatı ve indirim oranı. Kasiyer kutuları doldurur, adımları izler ve bulduğu fiyatı fişe ekler. Bu haftanın konuları kartta şu işlere karşılık geliyor:

Kartta Python’da Dikkat
Kartı yazıp kasaya koymak def indirimli_fiyat(fiyat, indirim_orani): ve girintili gövde Tanım gövdeyi çalıştırmaz
Kartı bir ürün için kullanmak indirimli_fiyat(800, 0.25) çağrısı Gövde her çağrıda yeniden çalışır
Boş kutular ve kutulara yazılan değerler fiyat ve indirim_orani parametre, 800 ve 0.25 argüman Kutulardan biri boş kalırsa (indirimli_fiyat(800)) çağrı TypeError verir
Bulunan fiyatı kasiyere vermek return print() fiyatı yalnız ekranda gösterir. Çağıran kodun eline None geçer, iki fiyat toplanamaz
“Hediyeyse 0 ver, hesaba geçme” return 0 return çalışınca fonksiyon biter, alttaki hesap satırları çalışmaz
KDV için ayrı bir kart kdv_ekle ayrı bir fonksiyon Kartlar ayrı ayrı denenir, yanlış sonucun hangi kartta çıktığı bulunur

Değiştir: kargo hesabını fonksiyona dönüştürün

Aşağıdaki programda kargo ücreti doğrudan hesaplanıyor:

Bu hesabı şöyle bir fonksiyona dönüştürün:

def kargo_ucreti(sepet_tutari):
    ...

Fonksiyon şu değerleri döndürmelidir:

  • 500 TL ve üzeri için 0
  • Daha düşük tutarlar için 39.90

Python 39.90’ı ekrana 39.9 diye yazar. İkisi aynı sayıdır. Fonksiyonu 650, 500 ve 499 ile çağırıp sonuçları yazdırın.

def kargo_ucreti(sepet_tutari):
    if sepet_tutari >= 500:
        return 0
    return 39.90

print(kargo_ucreti(650))
print(kargo_ucreti(500))
print(kargo_ucreti(499))

İlk return çalışırsa fonksiyon orada biter, bu yüzden else yazmak gerekmez. else ile yazılmış bir çözüm de doğrudur.

Üret: indirimli fiyat fonksiyonu

Kasadaki indirim kartını Python’a çevirin: bir ürünün fiyatını ve indirim oranını alan, indirim sonrası fiyatı döndüren bir fonksiyon yazın.

Başlangıç:

pass hiçbir şey yapmayan bir deyimdir. Fonksiyonun gövdesi boş kalamadığı için yer tutar. Kodunuzu yazınca silin. Beklenen sonuç 600.0’dır.

Kabul kriterleri:

  • Fonksiyonun adı indirimli_fiyat olmalı.
  • İki parametre kullanılmalı.
  • İndirim miktarı fiyat * indirim_orani ilişkisiyle hesaplanmalı.
  • Sonuç return ile döndürülmeli.
  • Fonksiyon farklı fiyat ve oranlarla da çalışabilmeli.

Önce indirim = fiyat * indirim_orani hesaplanabilir. Sonra fiyat - indirim döndürülebilir.

def indirimli_fiyat(fiyat, indirim_orani):
    indirim = fiyat * indirim_orani
    return fiyat - indirim

print(indirimli_fiyat(800, 0.25))

Sıra sizde: hediye ürün ve fiş toplamı

Fonksiyona üçüncü bir parametre ekleyin: hediye_mi. Ürün hediyeyse fonksiyon 0 döndürsün ve indirim hesabına hiç geçmesin. Sonra fonksiyonu iki kez çağırıp müşterinin fişini toplayın: 800 TL’lik %25 indirimli ürün ile 200 TL’lik %10 indirimli ürün.

Beklenen çıktı:

Satır Beklenen
indirimli_fiyat(800, 0.25, True) 0
Fiş toplamı (iki ürün de hediye değil) 780.0

Gövdenin ilk satırı if hediye_mi: olsun ve altında return 0 dursun. Fiş toplamı için indirimli_fiyat(800, 0.25, False) + indirimli_fiyat(200, 0.10, False) yazabilirsiniz.

def indirimli_fiyat(fiyat, indirim_orani, hediye_mi):
    if hediye_mi:
        return 0
    indirim = fiyat * indirim_orani
    return fiyat - indirim

print(indirimli_fiyat(800, 0.25, True))
fis_toplami = indirimli_fiyat(800, 0.25, False) + indirimli_fiyat(200, 0.10, False)
print(fis_toplami)

Sınav provası

Önce kendi cevabınızı seçin, sonra cevap anahtarında her şıkkın neden doğru ya da yanlış olduğunu okuyun. Yanlış şıklar rastgele yazılmadı; bu konuda öğrencilerin gerçekten yaptığı hatalardan seçildi. Sınav soruları da aynı yolla hazırlanır.

1. Fonksiyon tanımı ile fonksiyon çağrısı arasındaki fark nedir?

  • A. Tanım fonksiyonu kaydeder, çağrı onu çalıştırır
  • B. Tanım fonksiyonu bir kez çalıştırır, çağrı ise tekrar çalıştırır
  • C. Tanım parantezli, çağrı parantezsiz yazılır
  • D. İkisi aynı şeydir, def yazımı isteğe bağlıdır
  • E. Tanım dosyanın sonunda, çağrı başında yer alır

2. Aşağıdaki program neden hata verir?

print(selamla())

def selamla():
    return "Merhaba"
  • A. Bir fonksiyon print() içinde çağrılamaz
  • B. Parametresi olmayan bir fonksiyon çağrılamaz
  • C. return ile metin döndürülemez
  • D. Çağrı anında selamla henüz tanımlı değildir
  • E. return yerine print() kullanılmalıydı

3. def toplam(a, b): tanımındaki a ve b ile toplam(4, 7) çağrısındaki 4 ve 7 sırasıyla nedir?

  • A. Dördü de argümandır
  • B. Dördü de parametredir
  • C. a ve b parametredir, 4 ve 7 dönüş değeridir
  • D. a ve b argümandır, 4 ve 7 parametredir
  • E. a ve b parametredir, 4 ve 7 argümandır

4. Aşağıdaki program çalıştırılınca ne olur?

def alan(en, boy):
    return en * boy

print(alan(5))
  • A. Hata vermez, eksik argüman 0 sayılır
  • B. TypeError verir, boy için argüman verilmemiştir
  • C. NameError verir, boy adı hiçbir yerde tanımlı değildir
  • D. Hata vermez, 5 ikisine birden atanır
  • E. ValueError verir, 5 geçersiz bir değerdir

5. print() ile return arasındaki temel fark nedir?

  • A. return kullanan bir fonksiyon ekrana yazamaz
  • B. print() değeri gösterir, return çağıran koda geri verir
  • C. İkisi aynı işi yapar, return fonksiyon içinde kullanılır
  • D. print() metinleri, return sayıları taşır
  • E. return ekrana yazar, print() değeri saklar

6. Aşağıdaki program neden Toplam: None yazdırır?

def topla(a, b):
    print(a + b)

sonuc = topla(2, 3)
print("Toplam:", sonuc)
  • A. Fonksiyon iki argümanla iki değer döndürmeye çalıştığı için
  • B. print() çağrısı toplamı bozduğu için
  • C. sonuc değişkeni yanlış adlandırıldığı için
  • D. Fonksiyon sonucu yazdırıp döndürmediği için
  • E. a + b işlemi fonksiyon içinde yapılamadığı için

7. Aşağıdaki program ne yazdırır?

def kontrol(puan):
    if puan >= 50:
        return "Geçti"
    return "Kaldı"
    print("Bu satır")

print(kontrol(80))
  • A. Kaldı
  • B. Geçti ve Kaldı
  • C. None
  • D. Geçti ve Bu satır
  • E. Geçti

8. Aşağıdaki program ne yazdırır?

def isaret(sayi):
    if sayi > 0:
        return "pozitif"
    if sayi < 0:
        return "negatif"

print(isaret(0))
  • A. None
  • B. negatif
  • C. 0
  • D. Hata verir, fonksiyon her durumda bir return çalıştırmalıdır
  • E. Hiçbir şey yazmaz

9. Aşağıdaki program ne yazdırır?

def iki_kat(x):
    return x * 2

a = iki_kat(3)
b = iki_kat(a)
print(b)
  • A. 24
  • B. None
  • C. 12
  • D. 6
  • E. 3

10. Bir fonksiyon yalnızca kod tekrarını azaltmak için değil, başka hangi nedenle de yararlıdır?

  • A. Programın daha az bellek kullanmasını sağlar
  • B. Değişkenlerin tür dönüşümünü kendiliğinden yapar
  • C. Problemi ayrı ayrı denenebilen parçalara böler
  • D. Fonksiyon içindeki söz dizimi hatalarını engeller
  • E. Programın daha hızlı çalışmasını sağlar

1. Doğru: A. def satırı yalnızca adı ve gövdeyi kaydeder. Gövdeyi çalıştırmaz. Gövde ancak fonksiyon adı parantezle çağrıldığında, o anda çalışır.

  • B yanlış: def satırı da yürütülen bir satır olduğu için gövdenin o anda çalıştığı sanılabilir. Ama tanım gövdeyi hiç çalıştırmaz. Gövde ilk kez ilk çağrıda çalışır.
  • C yanlış: İki satırın yazımı farklı olduğu için parantezin yalnızca birinde bulunduğu sanılabilir. Ama ikisinde de parantez vardır. Tanımda parametreler, çağrıda argümanlar bulunur.
  • D yanlış: print() gibi yerleşik fonksiyonları def yazmadan kullandığımız için def gereksiz görünebilir. Ama kendi fonksiyonunuz def olmadan oluşmaz. Tanım ve çağrı ayrı adımlardır.
  • E yanlış: Programın asıl işi çağrıda yapıldığı için onun başa konacağı düşünülebilir. Ama sıra tam tersi olmalıdır: ad kullanılmadan önce tanımlanır.

2. Doğru: D. Python satırları sırayla yürütür. İlk satır çalıştığında def satırına henüz gelinmemiştir. Ad var olmadığı için NameError oluşur.

  • A yanlış: İç içe iki çağrı ilk bakışta karışık göründüğü için hatalı sanılabilir. Ama çağrılabilir. Dönüş değeri doğrudan print()e verilir.
  • B yanlış: Fonksiyon örneklerinin çoğu parametre aldığı için boş parantez eksik görünebilir. Ama parametresiz fonksiyonlar boş parantezle çağrılır ve bu geçerlidir.
  • C yanlış: Örneklerde return çoğu zaman bir hesabın sonucunu döndürdüğü için yalnız sayı döndürüyormuş gibi görünebilir. Ama return her türden değeri döndürür. Sorun çağrının tanımdan önce gelmesidir.
  • E yanlış: print() ile return sık karıştırıldığı için sorun orada aranabilir. Ama return doğru kullanılmış. Sorun çağrının tanımdan önce gelmesi.

3. Doğru: E. Parametre tanımdaki addır. Argüman çağrıda o ada verilen değerdir.

  • A yanlış: Günlük dilde “fonksiyona verilenler” diye hepsine tek ad verilebilir. Ama tanımdaki a ve b henüz bir değer değil, değer bekleyen addır. Bunlar parametredir.
  • B yanlış: Dördü de parantezin içinde durduğu için aynı adı taşıdıkları sanılabilir. Ama çağrıda verilen 4 ve 7 argümandır.
  • C yanlış: Tanımdaki adların parametre olduğu doğrudur. Ama 4 ve 7 çağrıda verilen değerlerdir, yani argümandır. Dönüş değeri, fonksiyonun return ile geri verdiği değerdir.
  • D yanlış: İki terim hep birlikte geçtiği için hangisinin tanımda, hangisinin çağrıda olduğu kolayca karışır. Terimler ters yazılmış: tanımdaki ad parametre, çağrıdaki değer argümandır.

4. Doğru: B. alan iki zorunlu parametre bekler, çağrıda yalnızca 5 verilmiş. Python eksik argümanı kendiliğinden tamamlamaz. Fonksiyonun gövdesi daha çalışmadan çağrı hata verir.

  • A yanlış: Hesaplarda eksik değer çoğu zaman sıfır sayıldığı için akla yatkındır. Ama böyle bir varsayılan yoktur. Varsayılan istenirse tanımda yazılır.
  • C yanlış: Gövdede boy kullanılıyor ama bir değeri yok. Bu tanımsız ad gibi görünür. Ama boy tanımda yer alan bir parametredir. Sorun, ona değer verilmemesi.
  • D yanlış: Karede en ile boy eşit olduğu için tek bir değer ikisine yetecekmiş gibi görünebilir. Ama bir argüman yalnızca bir parametreye karşılık gelir.
  • E yanlış: Hatalı bir değer verildiği hissi ValueErrorı akla getirir. Ama 5 geçerli bir sayıdır. Sorun argüman sayısında.

5. Doğru: B. Yalnızca ekrana yazdırmak, hesaplanan değeri fonksiyonun dönüş değeri yapmaz. return değeri çağıran koda geri verir. Çağıran kod bu değeri bir değişkene atayıp sonradan kullanabilir.

  • A yanlış: return ile ekrana yazmak ayrı işler olduğu için ikisi bir arada bulunamaz gibi görünebilir. Ama aynı fonksiyon hem yazdırıp hem değer döndürebilir.
  • C yanlış: İkisi de fonksiyonun sonucunu dışarı çıkarıyor gibi göründüğü için aynı sanılır. Ama aynı işi yapmazlar. Biri değeri gösterir, öteki geri verir.
  • D yanlış: print() çoğu örnekte metin yazdırdığı, return ise hesap sonucu döndürdüğü için böyle bir ayrım sezilebilir. Ama ikisi de her türle çalışır.
  • E yanlış: İki komutun ayrı işler yaptığı bilinse de hangisinin ne yaptığı kolayca karışır. Ama görevler ters yazılmış.

6. Doğru: D. Ekrandaki 5 fonksiyonun içindeki print() çıktısıdır. Fonksiyonda return olmadığı için çağrı None döndürür ve sonuc None olur. Çağıran koda değer ancak return ile gider.

  • A yanlış: İki değer verip tek bir None almak, bir şeylerin karıştığı hissini verir. Ama argüman sayısıyla dönüş değeri arasında böyle bir ilişki yoktur.
  • B yanlış: Fonksiyonda return yerine duran tek satır print() olduğu için şüphe ona gider. Ama print() değeri değiştirmez, yalnızca gösterir. Eksik olan returndur.
  • C yanlış: Beklenmeyen bir değer görünce değişkenin yanlış yazıldığı düşünülebilir. Ama ad seçimi değeri etkilemez. Hangi ad verilse None yazılırdı.
  • E yanlış: Toplamın dışarı çıkmaması işlemin hiç yapılmadığı izlenimini verir. Ama işlem yapılabilir ve zaten yapılıyor. Ekranda 5 görünüyor.

7. Doğru: E. return çalıştığı anda fonksiyon biter. Sonrasındaki hiçbir satıra ulaşılmaz.

  • A yanlış: return "Kaldı" satırı if bloğunun dışında ve gövdenin sonunda durduğu için son sözü o söylüyormuş gibi okunur. Ama 80 >= 50 doğrudur ve fonksiyon ilk return’de biter.
  • B yanlış: İki return alt alta durduğu için ikisinin de sırayla çalıştığı sanılabilir. Ama ilk return fonksiyonu sonlandırır, ikincisine sıra gelmez.
  • C yanlış: return’den sonra erişilemeyen bir satır görünce fonksiyonun bozulduğu ve değer döndürmediği sanılabilir. Ama fonksiyon "Geçti" değerini açıkça döndürüyor.
  • D yanlış: Kodda print("Bu satır") açıkça yazılı olduğu için bir yerde çalışacağı düşünülür. Ama return satırından sonraki satırlara hiç ulaşılmaz.

8. Doğru: A. 0 iki koşulu da sağlamaz, bu yüzden iki return satırı da çalışmaz. Fonksiyon gövdenin sonuna return görmeden ulaşır ve None döndürür. print() bu değeri yazar.

  • B yanlış: pozitif olmayan her sayı için ikinci return çalışacakmış gibi düşünülür. Ama ikinci satır da bir koşula bağlıdır ve 0 < 0 yanlıştır.
  • C yanlış: Fonksiyona 0 verildiği için aynı değerin geri döneceği sanılabilir. Ama fonksiyon argümanı kendiliğinden geri vermez. Çalışan bir return yoksa None döner.
  • D yanlış: Değer döndüren fonksiyonların her yolda return içermesi gerektiği sanılabilir. Ama Python bunu zorunlu tutmaz. return çalışmayan yolda hata vermeden None döndürür.
  • E yanlış: return çalışmadığı için print()e verilecek bir şey kalmadığı düşünülür. Ama fonksiyon yine bir değer döndürür: None. print() de bunu ekrana yazar.

9. Doğru: C. a 6 olur, sonra 6’nın iki katı olan 12 bye atanır.

  • A yanlış: Kodda iki_kat adı üç kez geçtiği (tanım ve iki çağrı) için değerin üç kez katlandığı sanılabilir. Ama tanım fonksiyonu çalıştırmaz. Yalnızca iki çağrı var.
  • B yanlış: None bu bölümde sık geçtiği için dönüş değeri olan her soruda akla gelebilir. Ama iki_kat değeri return ile açıkça döndürüyor.
  • D yanlış: iki_kat(3) çağrısı yalnız bir kez düşünülürse sonuç 6 bulunur. Ama bu a’nın değeridir. b, a’yı yeniden ikiye katlayan ikinci çağrının sonucudur.
  • E yanlış: b = iki_kat(a) satırında a yerine ilk argüman olan 3 düşünülürse çağrılar hiç etki etmiyormuş gibi görünür. Ama ilk çağrı değeri zaten ikiye katlıyor.

10. Doğru: C. Her parça ayrı ayrı okunabilir, denenebilir ve düzeltilebilir. Küçük bir fonksiyonun doğruluğu tek başına sınanabilir. Hata da tek bir yerde aranır.

  • A yanlış: Tekrar eden kod azalınca programın da hafifleyeceği düşünülebilir. Ama fonksiyon çağrısı kendi başına bellek kazandırmaz.
  • B yanlış: int() gibi dönüşümler de birer fonksiyon olduğu için her fonksiyonun dönüşüm yaptığı sanılabilir. Ama tür dönüşümünü yine int() gibi fonksiyonlarla açıkça yazmanız gerekir.
  • D yanlış: Düzenli yazılmış kodun daha az hata vereceği düşünülebilir. Ama söz dizimi hataları fonksiyon içinde de çıkar.
  • E yanlış: Düzenli görünen kodun daha hızlı çalışacağı düşünülebilir. Ama fonksiyona ayırmak hızı artırmaz. Yararı kodu daha kolay okunur ve sınanır yapmasıdır.

Tek sayfa özet

Bu hafta programı adlandırılmış ve yeniden kullanılabilir parçalara ayırmaya başladık.

  • Fonksiyon def ile tanımlanır, adı ve parantezleriyle çağrılır. Parantezsiz ad fonksiyonu çağırmaz.
  • Çağrı satırı çalıştığında fonksiyon henüz tanımlanmamışsa NameError oluşur. Bu yüzden tanımları onları kullanan koddan önce yazın.
  • Parametre fonksiyon tanımındaki addır, argüman çağrıda verilen değerdir. Argümanlar parametrelere yazıldıkları sırayla eşlenir.
  • Argüman sayısı parametre sayısını tutmazsa çağrı TypeError verir.
  • print() değeri ekrana yazar, return ise fonksiyonun sonucunu çağıran koda gönderir.
  • Hiçbir return satırı çalışmayan fonksiyon örtük olarak, yani kodda yazılmadan None döndürür.
  • return çalıştığında fonksiyon sona erer.
  • Fonksiyonun dönüş değeri başka değişkenlerde ve ifadelerde kullanılabilir.
  • İyi yazılmış küçük bir fonksiyonun işi çoğu zaman tek cümleyle anlatılabilir.
  • Problemi küçük fonksiyonlara ayırmak kodu okumayı, denemeyi ve hatayı bulmayı kolaylaştırır.
  • Kasadaki indirim kartı bir fonksiyondur: boş kutular parametre, kutulara yazılan değerler argüman, kasiyere verilen fiyat dönüş değeridir.

Bir sonraki bölümde fonksiyon tasarlarken “çalışıyor mu?” sorusunun yanında şunları da soracağız: Hangi girdileri kabul etmeli, hangi sonucu döndürmeli, bunu nasıl doğrularız?

Bu bölümün kazanımları

Bu bölümü bitiren öğrenci:

  • Fonksiyon tanımı ile fonksiyon çağrısını birbirinden ayırt eder.
  • Parametre ile argümanı ayırt eder ve sayıları uyuşmadığında oluşan TypeError hatasını açıklar.
  • print() ile return arasındaki farkı açıklar.
  • return çalıştığında fonksiyonun sona erdiğini belirler.
  • Değer döndürmeyen bir fonksiyonun None döndürdüğünü açıklar.
  • Fonksiyonun dönüş değerini başka ifadelerde ve çağrılarda kullanır.
  • Problemi küçük fonksiyonlara ayırmanın gerekçesini açıklar.
Başa dön