Nesne Tabanlı Programlama

7 - Fonksiyonlar

Emre Can Yılmaz

Ondokuz Mayıs Üniversitesi

2024

Fonksiyonlar: Kodunuzu Parçalara Ayırın!

  • Fonksiyonlar, belirli bir görevi yerine getiren, yeniden kullanılabilir kod bloklarıdır.
  • Fonksiyonlar:
    • Kod tekrarını azaltır.
    • Kod okunabilirliğini arttırır.
    • Kod bakımını kolaylaştırır.

Fonksiyon Tanımlama

  • Python’da bir fonksiyon tanımlamak için def anahtar kelimesini kullanırız.

Sözdizimi

def fonksiyon_adi(parametre1, parametre2, ...):
    """Fonksiyonun açıklaması (docstring)"""
    # Fonksiyonun gövdesi
    # Yapılacak işlemler
    return deger  # İsteğe bağlı

Örnek 1: Basit Bir Fonksiyon

def selamla():
    """Ekrana bir selamlama mesajı yazdırır."""
    print("Merhaba!")

selamla() # Fonksiyonu çağırma

Örnek 2: Parametre Alan Fonksiyon

def selamla(isim):
    """Verilen isimle bir selamlama mesajı yazdırır."""
    print(f"Merhaba {isim}!")

selamla("Ahmet")  # Çıktı: Merhaba Ahmet!
selamla("Ayşe")   # Çıktı: Merhaba Ayşe!

Örnek 3: Değer Döndüren Fonksiyon

def sum(num1, num2):
    """İki sayıyı toplar ve sonucu döndürür."""
    result = num1 + num2
    return result

Örnek 4: Değer Döndüren Fonksiyon

def find_largest_number(number1, number2, number3):
    """Returns the largest of three numbers."""
    if number1 >= number2 and number1 >= number3:
        return number1
    elif number2 >= number1 and number2 >= number3:
        return number2
    else:
        return number3

Fonksiyon Çağırma

  • Bir fonksiyonu çağırmak için, fonksiyonun adını ve ardından parantez içinde argümanları (eğer varsa) yazarız.

Örnek

def sum(num1, num2):
    """İki sayıyı toplar ve sonucu döndürür."""
    result = num1 + num2
    return result

print(topla(5, 3))
print(topla(16, 7))
8
23

Geri Dönüş Değerleri (Return Values)

  • Fonksiyonlar, işlemlerini tamamladıktan sonra bir değer döndürebilir. Bu değer, return ifadesi ile belirtilir.
  • Eğer return ifadesi kullanılmazsa, fonksiyon None değerini döndürür.

Örnek

def mutlak_deger(sayi):
    """Verilen sayının mutlak değerini döndürür."""
    if sayi < 0:
        return -sayi
    else:
        return sayi

sonuc = mutlak_deger(-10)
print(sonuc)
10

Fonksiyonların Kapsamı (Scope)

  • Bir değişkenin kapsamı (scope), o değişkenin programın hangi bölümlerinde erişilebilir olduğunu belirler.
  • Fonksiyonlar, kendi yerel kapsamlarına (local scope) sahiptir. Bu, fonksiyon içinde tanımlanan değişkenlerin, fonksiyon dışında erişilemeyeceği anlamına gelir.

Örnek

x = 10  # Global değişken x

def function():
    x = 5   # Local değişken x
    print("Fonksiyon içinde x: ", x)

function()  # Fonksiyon çağrısı
print("Fonksiyon dışında x: ", x)
Fonksiyon içinde x: 5
Fonksiyon dışında x: 10

Global Değişkenleri Değiştirme

  • Bir fonksiyon içinde global bir değişkeni değiştirmek için, global anahtar kelimesini kullanmalıyız.

Warning

global anahtar kelimesini dikkatli kullanın! Fonksiyonlar içinde global değişkenleri değiştirmek, kodun okunabilirliğini ve bakımını zorlaştırabilir ve beklenmedik sonuçlara yol açabilir. Mümkün olduğunca, fonksiyonların yan etkilerinden kaçınmak ve değerleri return ifadesi ile döndürmek daha iyi bir uygulamadır.

Örnek

x = 10 # global x

def fonksiyon():
    global x
    x = 20  # global x'i güncelle

print(x)
fonksiyon()
print(x)
10
20

İç İçe Fonksiyonlar ve Kapsamlar

  • Bir fonksiyonun içinde başka bir fonksiyon tanımlayabiliriz.
  • İçteki fonksiyon, dıştaki fonksiyonun yerel kapsamına ve global kapsama erişebilir.
  • İçteki fonksiyon, dıştaki fonksiyonun yerel değişkenini değiştirmek için nonlocal anahtar kelimesini kullanabilir.

Örnek

def dis_fonksiyon():
    a = 10
    print(f"Dış fonksiyon içinde a: {a}")
    def ic_fonksiyon():
        nonlocal a
        a = 20
        print(f"İç fonksiyon içinde a: {a}")

    ic_fonksiyon()
    print(f"Dış fonksiyon içinde a: {a}")

dis_fonksiyon()
Dış fonksiyon içinde a: 10
İç fonksiyon içinde a: 20
Dış fonksiyon içinde a: 20

Varsayılan Parametre Değerleri

  • Fonksiyon tanımlarında parametrelere varsayılan değerler atayabiliriz.
  • Bu sayede, fonksiyon çağrılırken bu parametreler için bir argüman verilmezse, varsayılan değer kullanılır.

Örnek 1: Varsayılan Parametre

def selamla(isim="Kullanıcı"):
    """Verilen isimle bir selamlama mesajı yazdırır.
    İsim verilmezse, "Kullanıcı" ismi kullanılır.
    """
    print(f"Merhaba {isim}!")

selamla()
selamla("Ahmet")
Merhaba Kullanıcı!
Merhaba Ahmet!

Örnek 2: Varsayılan Parametre

def us_al(sayi, us=2):
    """Verilen sayıyı verilen üsse yükseltir.
    Üs belirtilmezse, varsayılan olarak 2 kullanılır.
    """
    return sayi ** us

print(us_al(3))
print(us_al(3, 3))
9
27

Değişken Sayıda Argüman (*args ve **kwargs)

  • Fonksiyonlar, değişken sayıda argüman alabilir.
  • *args ile değişken sayıda konumsal argüman,
  • **kwargs ile de değişken sayıda anahtar kelime argümanı alabiliriz.

Örnek 1: *args

def topla(*args):
    """Değişken sayıda sayıyı toplar."""
    toplam = 0
    for sayi in args:
        toplam += sayi
    return toplam

print(topla(1, 2))
print(topla(10, 20, 30, 40))
3
100

Örnek 2: **kwargs

def ogrenci_bilgileri(**kwargs):
    """Öğrenci bilgilerini yazdırır."""
    for anahtar, deger in kwargs.items():
        print(f"{anahtar}: {deger}")

ogrenci_bilgileri(isim="Ahmet", soyisim="Yılmaz", numara=12345)
isim: Ahmet
soyisim: Yılmaz
numara: 12345

Sık Yapılan Hatalar - args ve kwargs:

def my_func(*args, **kwargs):
    print("Args:", args)
    print("Kwargs:", kwargs)

Pozisyonel argümandan sonra anahtar argüman yazılmamalıdır.

Yanlış Kullanım

my_func(1, some_key="value", "another_value")  # Bu hata verir.

Doğru Kullanım

my_func(1, "another_value", some_key="value")

Lambda Fonksiyonları

  • Lambda fonksiyonları, Python’da kısa ve basit fonksiyonları tek satırda tanımlamak için kullanılır.
  • Özellikle, fonksiyonun karmaşık bir yapısı yoksa ve sadece bir ifadeyi hesaplayıp döndürüyorsa, lambda fonksiyonları kullanışlı olabilir.
  • lambda fonksiyonlarının bir adı yoktur ve genellikle bir değişkene atanır.

Sözdizim

lambda argümanlar: ifade

Örnek 1: Lambda Fonksiyonu

kare_al = lambda x: x*x
print(kare_al(5))
25

Örnek 2: Lambda Fonksiyonu

cift_mi = lambda x: x%2 == 0
topla = lambda x, y: x + y

print(cift_mi(6))
print(cift_mi(5))
print(topla(3, 5))
True
False
8

Lambda Fonksiyonları Ne Zaman Kullanılmamalı?

Warning

Karmaşık İşlemler: Eğer fonksiyonunuzda birden fazla ifade veya döngü varsa, lambda fonksiyonu kullanmak kodun okunabilirliğini azaltabilir. Bu durumlarda normal fonksiyon tanımını kullanmak daha iyidir.

Yan Etkiler: Lambda fonksiyonları, genellikle sadece bir ifadeyi hesaplayıp döndürdükleri için yan etkiler (global değişkenleri değiştirmek, dosya işlemleri yapmak gibi) yaratmak için uygun değildir. Eğer fonksiyonunuzun yan etkileri olması gerekiyorsa, normal def ile fonksiyon tanımını kullanmalısınız.

Özetle, lambda fonksiyonları, kısa ve basit fonksiyonları tek satırda tanımlamak için kullanışlı bir araçtır. Ancak, karmaşık fonksiyonlar veya yan etkiler gerektiren durumlarda normal fonksiyon tanımını kullanmak daha uygun olacaktır.

pass İfadesi

  • pass ifadesi, Python’da hiçbir şey yapmayan bir ifadedir.
  • Genellikle kod bloklarını henüz tamamlanmadığı veya geçici olarak boş bırakılması gereken durumlarda kullanılır.
def fonksiyon():
  pass # Bu fonksiyon daha sonra tamamlanacak.

Özyineli Fonksiyonlar (Recursive Functions)

  • Özyineli fonksiyonlar, kendini çağıran fonksiyonlardır.
  • Bazı problemleri çözmek için oldukça zarif ve etkili bir yöntemdir.
  • Özyineli fonksiyonlar, problemi daha küçük alt problemlere bölerek çözer ve her alt problemi aynı fonksiyonu kullanarak tekrar tekrar çözer.

Warning

Özyineli fonksiyon yazarken dikkatli olun! Eğer temel durumu doğru bir şekilde tanımlamazsanız, fonksiyon sonsuz döngüye girebilir ve programınız çökebilir.

Özyinelemenin Temel Mantığı

  • Temel Durum (Base Case): Her özyineli fonksiyonun, özyinelemenin durduğu bir temel durumu olmalıdır. Temel durum, problemin en küçük ve çözümü bilinen halidir.

  • Özyineli Adım (Recursive Step): Temel duruma ulaşılmadığı sürece, fonksiyon kendini daha küçük bir girdiyle tekrar çağırır. Her çağrıda, problem daha da basitleştirilir.

Örnek: Faktöriyel Hesaplama

def faktoriyel(n):
    """Verilen sayının faktöriyelini hesaplar."""
    if n == 0:
        return 1
    else:
        return n * faktoriyel(n-1)

print(faktoriyel(5)) # Çıktı: 120

Adım Adım Özyineleme

faktoriyel(5) çağrısı nasıl çalışır?

  1. faktoriyel(5) çağrılır. 5, 0’a eşit olmadığı için else bloğuna girilir.
  2. faktoriyel(5) = 5 * faktoriyel(4) olarak hesaplanır.
  3. faktoriyel(4) = 4 * faktoriyel(3) olarak hesaplanır.
  4. Bu işlem faktoriyel(1) ve faktoriyel(0)’a kadar devam eder.
  5. faktoriyel(0)’ın değeri 1’dir.
  1. Döndürülen değerler zinciri geriye doğru işlenir:
    • faktoriyel(1) = 1
    • faktoriyel(2) = 2 * faktoriyel(1) = 2 * 1 = 2
    • faktoriyel(3) = 3 * faktoriyel(2) = 3 * 2 = 6
    • faktoriyel(4) = 4 * faktoriyel(3) = 4 * 6 = 24
    • faktoriyel(5) = 5 * faktoriyel(4) = 5 * 24 = 120
    • Sonuç: 120

Örnek Problem

Fibonacci dizisi

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

Örnek: Fibonacci Dizisi

def fibonacci(n):
    """Fibonacci dizisinin n'inci elemanını döndürür."""
    if n <= 1:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(6)) # Çıktı: 8

Adım Adım Özyineleme

fibonacci(6) çağrısı nasıl çalışır?

  1. fibonacci(6) çağrılır. 6, 1’den küçük olmadığı için else bloğuna girilir.
  2. fibonacci(6) = fibonacci(5) + fibonacci(4) olarak hesaplanır.
  3. fibonacci(5) = fibonacci(4) + fibonacci(3) olarak hesaplanır.
  4. Bu işlem fibonacci(1) ve fibonacci(2)’ye kadar devam eder.
  5. fibonacci(1) ve fibonacci(2)’nin değerleri sırasıyla 1 ve 1’dir.
  1. Döndürülen değerler zinciri geriye doğru işlenir:
    • fibonacci(2) = fibonacci(1) + fibonacci(0) = 1 + 0 = 1
    • fibonacci(3) = fibonacci(2) + fibonacci(1) = 1 + 1 = 2
    • fibonacci(4) = fibonacci(3) + fibonacci(2) = 2 + 1 = 3
    • fibonacci(5) = fibonacci(4) + fibonacci(3) = 3 + 2 = 5
    • fibonacci(6) = fibonacci(5) + fibonacci(4) = 5 + 3 = 8

Fonksiyon Tasarımı İpuçları

  • Fonksiyonlar kısa ve öz olmalı.
  • Her fonksiyon tek bir görevi yerine getirmeli.
  • Fonksiyon isimleri anlamlı ve açıklayıcı olmalı.
  • Fonksiyonlar iyi dokümante edilmeli.

Alıştırmalar

  1. Kullanıcıdan iki sayı alan ve bu sayıların toplamını, farkını, çarpımını ve bölümünü hesaplayan 4 ayrı fonksiyon yazın.
  2. Kullanıcıdan bir metin alan ve bu metnin içindeki sesli harflerin sayısını döndüren bir fonksiyon yazın.
  3. Kullanıcıdan bir liste alan ve bu listedeki en büyük sayıyı bulan bir fonksiyon yazın.
  4. Girilen bir sayının asal olup olmadığını kontrol eden bir fonksiyon yazın.
  5. Verilen bir sayının fibonacci sayısını hesaplayan özyineli bir fonksiyon yazın.
  1. Kullanıcıdan bir cümle alın ve bu cümledeki kelimeleri bir liste olarak döndüren bir fonksiyon yazın.
  2. Bir listenin elemanlarını toplayan bir fonksiyon yazın, ancak liste boş ise 0 döndürsün.
  3. Bir metni tersine çeviren bir fonksiyon yazın. Örneğin, “Merhaba” metni “abahreM” olarak döndürülsün.
  4. Bir metindeki her kelimenin ilk harfini büyük harfe dönüştüren bir fonksiyon yazın. Örneğin, “python programlama dili” metni “Python Programlama Dili” olarak döndürülsün.
  5. Girilen bir sayının 2’nin kuvveti olup olmadığını kontrol eden bir fonksiyon yazın.