Nesne Tabanlı Programlama

12 - Yüksek Mertebeden Fonksiyonlar ve Liste Üreteçleri

Emre Can Yılmaz

Ondokuz Mayıs Üniversitesi

2024

Yüksek Mertebeden Fonksiyonlar ve Liste Üreteçleri

  • Bu bölümde, Python’da iterable’lar (listeler, demetler vb.) üzerinde işlemler yapmak için kullanılan map, filter, zip ve reduce gibi yüksek mertebeden fonksiyonları (higher-order functions) ve liste üreteçlerini öğreneceğiz.

  • Tanım: Başka bir fonksiyonu argüman olarak alan veya sonuç olarak fonksiyon döndüren fonksiyonlara “yüksek mertebeden fonksiyon” denir.

  • Bu araçlar, kodunuzu daha öz, okunabilir ve verimli hale getirmenize yardımcı olur.

Yinelenebilir Nesneler (Iterable)

  • Yinelenebilir nesne (iterable), elemanları üzerinde sırayla dolaşabileceğimiz bir nesnedir.
  • Listeler, demetler, stringler, dosyalar ve range nesneleri yinelenebilir nesne örnekleridir.
  • for döngüsü ile bu nesnelerin elemanları üzerinde dolaşabiliriz.
liste = [1, 2, 3]
for eleman in liste:
    print(eleman)

demet = (4, 5, 6)
for eleman in demet:
    print(eleman)

metin = "Python"
for karakter in metin:
    print(karakter)

Lambda Fonksiyonları: Anonim ve Kısa Fonksiyonlar

  • Lambda fonksiyonları, tek satırda tanımlanabilen isimsiz (anonim) fonksiyonlardır.

Sözdizimi:

lambda argümanlar: ifade
  • lambda: Lambda fonksiyonu tanımlamak için kullanılır.
  • argümanlar: Fonksiyonun alacağı argümanlar (virgülle ayrılmış).
  • ifade: Fonksiyonun döndüreceği değeri hesaplayan ifade.

Örnekler:

kare_al = lambda x: x * x
print(kare_al(5))  # Çıktı: 25

topla = lambda x, y: x + y
print(topla(3, 5))  # Çıktı: 8

cift_mi = lambda sayi: sayi % 2 == 0
print(cift_mi(4))   # Çıktı: True
print(cift_mi(7))   # Çıktı: False
  • Not: Lambda fonksiyonlarını bir değişkene atamak (kare = lambda x: x*x) yerine, genellikle map veya filter içinde anlık olarak kullanırız. İsimlendirilmiş fonksiyonlar için def kullanmak daha doğrudur.
  • Kısıt: Lambda gövdesinde sadece tek bir ifade yer alabilir. Çok satırlı kod blokları veya atama işlemleri yapılamaz.

map() Fonksiyonu: Her Elemana Aynı İşlemi Uygula

  • map() fonksiyonu, bir fonksiyonu bir yinelenebilir nesnenin her elemanına uygular ve sonuçları yeni bir map nesnesi olarak döndürür.

Sözdizimi:

map(fonksiyon, iterable)
  • fonksiyon: Yinelenebilir nesnenin her elemanına uygulanacak fonksiyon.
  • iterable: İşlem yapılacak yinelenebilir nesne.
  • Önemli: map (ve filter, zip) Python 3’te “Tembel” (Lazy) çalışır. Sonuçları bellekte tutmaz, istendiğinde üretir. Bu yüzden çıktıları görebilmek için list() veya tuple() içine alırız.

Örnekler (lambda fonksiyonu kullanmadan):

def kare_al(x):
    return x * x

sayilar = [1, 2, 3, 4, 5]
kareler = list(map(kare_al, sayilar))
print(kareler)  # Çıktı: [1, 4, 9, 16, 25]
def ilk_harf_buyuk(kelime):
    return kelime.capitalize()

kelimeler = ["elma", "armut", "muz"]
buyuk_harfler = list(map(ilk_harf_buyuk, kelimeler))
print(buyuk_harfler) # Çıktı: ['Elma', 'Armut', 'Muz']
# Tuple ile örnek
def kup_al(x):
    return x**3

sayilar = (1, 2, 3, 4, 5)
kupler = tuple(map(kup_al, sayilar))
print(kupler) # Çıktı: (1, 8, 27, 64, 125)

Örnekler (lambda fonksiyonu ile):

sayilar = [1, 2, 3, 4, 5]

kareler = list(map(lambda x: x * x, sayilar))
print(kareler)  # Çıktı: [1, 4, 9, 16, 25]
# Lambda ile kullanım (Tüm harfleri büyütme)
kelimeler = ["elma", "armut", "muz"]

# .upper() tüm harfleri büyütür
buyuk_harfler = list(map(lambda kelime: kelime.upper(), kelimeler))

print(buyuk_harfler)  # Çıktı: ['ELMA', 'ARMUT', 'MUZ']
sayilar = (1, 2, 3, 4, 5)
kupler = tuple(map(lambda x: x**3, sayilar))
print(kupler) # Çıktı: (1, 8, 27, 64, 125)

filter() Fonksiyonu: Elemanları Filtrele

  • filter() fonksiyonu, bir fonksiyonu bir yinelenebilir nesnenin her elemanına uygular ve fonksiyonun True döndürdüğü elemanlardan oluşan yeni bir filter nesnesi döndürür.

Sözdizimi:

filter(fonksiyon, iterable)
  • fonksiyon: Yinelenebilir nesnenin her elemanına uygulanacak ve True veya False döndüren fonksiyon.
  • iterable: İşlem yapılacak yinelenebilir nesne.

Örnekler (lambda fonksiyonu kullanmadan):

def cift_mi(x):
    return x % 2 == 0

sayilar = [1, 2, 3, 4, 5, 6]
cift_sayilar = list(filter(cift_mi, sayilar))
print(cift_sayilar)  # Çıktı: [2, 4, 6]
def uzun_mu(kelime):
    return len(kelime) > 5

kelimeler = ["elma", "armut", "karpuz", "muz"]
uzun_kelimeler = list(filter(uzun_mu, kelimeler))
print(uzun_kelimeler) # Çıktı: ['karpuz']

Örnekler (lambda fonksiyonu ile):

sayilar = [1, 2, 3, 4, 5, 6]

cift_sayilar = list(filter(lambda x: x % 2 == 0, sayilar))
print(cift_sayilar)  # Çıktı: [2, 4, 6]
kelimeler = ["elma", "armut", "karpuz", "muz"]
uzun_kelimeler = list(filter(lambda kelime: len(kelime) > 5, kelimeler))
print(uzun_kelimeler)  # Çıktı: ['karpuz']

zip() Fonksiyonu: Yinelenebilir Nesneleri Birleştir

  • zip() fonksiyonu, iki veya daha fazla yinelenebilir nesneyi birleştirerek, elemanlarını tuple’lar halinde gruplandırır ve yeni bir zip nesnesi döndürür.

Sözdizimi:

zip(iterable1, iterable2, ...)
  • iterable1, iterable2, ...: Birleştirilecek yinelenebilir nesneler.

Örnekler:

isimler = ["Ahmet", "Mehmet", "Ayşe"]
yaslar = [25, 30, 22]

# İki listeyi birleştirerek tuple'lar oluştur
birlesim = list(zip(isimler, yaslar))
print(birlesim)  # Çıktı: [('Ahmet', 25), ('Mehmet', 30), ('Ayşe', 22)]

# Sözlük oluşturma
sozluk = dict(zip(isimler, yaslar))
print(sozluk)  # Çıktı: {'Ahmet': 25, 'Mehmet': 30, 'Ayşe': 22}
  • Dikkat: Eğer listelerin uzunlukları birbirinden farklıysa, zip() işlemi en kısa listeye göre sonlanır. Uzun olan listenin artan elemanları işleme dahil edilmez.
isimler = ["Ahmet", "Mehmet", "Ayşe"] # 3 Eleman
yaslar = [25, 30] # 2 Eleman

# 'Ayşe' dışarıda kalır çünkü yaslar listesi daha kısa
birlesim = list(zip(isimler, yaslar))
print(birlesim)  # Çıktı: [('Ahmet', 25), ('Mehmet', 30)]

reduce() Fonksiyonu: Tek Bir Sonuç Üret

  • reduce() fonksiyonu, bir fonksiyonu bir yinelenebilir nesnenin elemanlarına soldan sağa doğru ardışık olarak uygular ve tek bir sonuç değeri döndürür.
  • functools modülünden içe aktarılması gerekir.

Sözdizimi:

from functools import reduce

reduce(fonksiyon, iterable[, başlangıç_değeri])
  • fonksiyon: İki argüman alan ve tek bir sonuç döndüren fonksiyon.
  • iterable: İşlem yapılacak yinelenebilir nesne.
  • başlangıç_değeri: İsteğe bağlı başlangıç değeri.

Örnekler (lambda kullanmadan):

from functools import reduce

def carp(x, y):
    return x * y

sayilar = [1, 2, 3, 4]
carpim = reduce(carp, sayilar)
print(carpim)  # Çıktı: 24
def topla(x, y):
    return x + y

sayilar = [1, 2, 3, 4]
toplam = reduce(topla, sayilar, 10) # Başlangıç değeri 10
print(toplam) # Çıktı: 20

Örnekler (lambda ile):

from functools import reduce

sayilar = [1, 2, 3, 4]

carpim = reduce(lambda x, y: x * y, sayilar)
print(carpim)  # Çıktı: 24
toplam = reduce(lambda x, y: x + y, sayilar, 10)  # Başlangıç değeri 10
print(toplam)  # Çıktı: 20

Liste Üreteçleri (List Comprehensions): Öz ve Okunaklı Liste Oluşturma

  • Liste üreteçleri, listeleri oluşturmanın öz ve okunabilir bir yoludur.
  • for döngüsü ve koşullu ifadeler kullanarak yeni listeler oluşturabilirsiniz.

Sözdizimi:

[ifade for eleman in iterable if koşul]
  • ifade: Yeni listeye eklenecek değer.
  • eleman: Iterable’ın her elemanı.
  • iterable: İşlem yapılacak iterable.
  • koşul: İsteğe bağlı bir koşul.

Liste üreteçlerinin nasıl çalıştığını anlamak için, öncelikle liste üreteci ifadesini bir döngü ve koşullu ifade kullanarak nasıl yazabileceğimize bakalım:

sayilar = [1, 2, 3, 4, 5]
kareler = []

for x in sayilar:
    kareler.append(x * x)

print(kareler) # Çıktı: [1, 4, 9, 16, 25]
  • Bu kod, sayilar listesindeki her sayının karesini alır ve kareler listesine ekler.
  • Aynı işlemi, liste üreteci kullanarak tek satırda yapabiliriz:
sayilar = [1, 2, 3, 4, 5]
kareler = [x * x for x in sayilar]
print(kareler)  # Çıktı: [1, 4, 9, 16, 25]

Örnek 1: Filtreleme (Koşul Sonda)

# Çift sayıların karesini içeren bir liste oluştur
cift_kareler = [x * x for x in sayilar if x % 2 == 0]
print(cift_kareler)  # Çıktı: [4, 16]

Önemli: Koşul İfadelerinin Konumu

Liste üreteçlerinde if ifadesinin yeri, yaptığı işi değiştirir:

  • Filtreleme (if sonda): Sadece koşulu sağlayanları listeye alır.
[x for x in sayilar if x > 5]
  • Seçim / Manipülasyon (if-else başta): Tüm elemanları alır ama koşula göre farklı değer üretir.
["Çift" if x % 2 == 0 else "Tek" for x in sayilar]
# Belirli bir koşulu sağlayan elemanlar için farklı bir işlem yapma:
sayilar = [1, 2, 3, 4, 5, 6]

yeni_sayilar = [x * 2 if x % 2 == 0 else x * 3 for x in sayilar]

print(yeni_sayilar)  # Çıktı: [3, 4, 9, 8, 15, 12]

Örnek: String İşlemleri

# String'lerden oluşan bir listeden, uzunluğu 5'ten büyük olanları seç ve büyük harfe çevir
kelimeler = ["elma", "armut", "karpuz", "muz"]

uzun_kelimeler = [kelime.upper() for kelime in kelimeler if len(kelime) > 5]

print(uzun_kelimeler) # Çıktı: ['KARPUZ']
isimler = ["ali", "veli", "ayşe", "fatma"]

# Her ismin ilk harfini büyük yap
buyuk_harf_isimler = [isim.capitalize() for isim in isimler]

print(buyuk_harf_isimler) # ['Ali', 'Veli', 'Ayşe', 'Fatma']
# Uzunluğu 4'ten küçük olan isimleri seç
kisa_isimler = [isim for isim in isimler if len(isim) < 4]

print(kisa_isimler)  # ['ali']
# İsimlerin uzunluklarını içeren bir liste oluşturun
isimler = ["ali", "veli", "ayşe"]

uzunluklar = [len(isim) for isim in isimler]

print(uzunluklar)  # Çıktı: [3, 4, 4]

Alıştırmalar

  1. Bir listedeki tüm sayıları 2 ile çarpın. (map kullanın - lambda ile ve lambda olmadan).
  2. Bir listedeki 5’ten büyük sayıları filtreleyin. (filter kullanın - lambda ile ve lambda olmadan).
  3. İki listeyi birleştirip elemanlarını tuple olarak içeren bir liste oluşturun. (zip kullanın).
  4. Bir listedeki tüm sayıların toplamını bulun. (reduce kullanın - lambda ile ve lambda olmadan).
  5. Liste üreteçleri kullanarak 1’den 10’a kadar olan tek sayıların karesini içeren bir liste oluşturun.
  6. Liste üreteçleri kullanarak bir string içindeki tüm sesli harfleri büyük harfe çevirin.
  1. Bir listedeki sayıların küplerini hesaplayan ve yeni bir liste olarak döndüren bir list comprehension yazın.
  2. Bir string listesinde, uzunluğu 5 karakterden fazla olan stringleri seçen ve küçük harfe çeviren bir list comprehension yazın.
  3. İki listeyi zip kullanarak birleştirin ve her bir eleman çiftini toplayan bir list comprehension yazın.
  4. Bir liste içindeki her bir sayının karesini alıp, bu karelerin çift olanlarını filtreleyen ve bu çift karelerin toplamını bulan bir program yazın. (map, filter ve reduce kullanın.)