Filter() fonksiyonu ile ilgili

Merhaba,
Diyelim elimde şöyle bir sözlük var:

notlar = {'Ahmet' : 60,
            'Sinan' : 50,
            'Mehmet' : 45,
            'Ceren' : 87,
            'Selen' : 99,
            'Cem' : 98,
            'Can' : 51,
            'Kezban' : 100,
            'Hakan' : 66,
            'Mahmut' : 80}

Şöyle bir fonksiyon tanımladım:

def suzgec(n):
    return n >= 70

print(*filter(suzgec, notlar.values()))

olarak çıktı aldığımda sözlük değerlerini tek tek suzgec fonksiyonunda girerek >70 olan değerleri ekrana basıyor. Buraya kadar problem yok. Ama aşağıdaki gibi bir fonksiyon tanımlarsam filter() fonsiyonu, sözlük değerlerinin karşılığı olan harf değerlerini girmiyor. Yani :

def not_durum(n):
    if n in range(0,50): return 'F'
    if n in range(50, 70): return 'D'
    if n in range(70, 80): return 'C'
    if n in range(80, 90): return 'B'
    if n in range(90, 101): return 'A

print(*filter(not_durum, notlar.values()))

çıktısı sözlük değerlerini sayı olarak ekrana basıyor:

60 50 45 87 99 98 51 100 66 80

filter() fonksiyonu, tanımladığım son fonksiyon için neden istediğim harf notları ekrana vermiyor?

https://docs.python.org/2/library/functions.html#filter
Buradaki kaynağı incelediğimde filter fonksiyonu, verilen fonksiyondan çıkan verinin bool değeri ile ilgileniyor. Buna göre filtreleme yapıyor. İlk örnekte 70 ve üstü için True olduğu için 70 ve üstü olan notları çıktı olarak veriyor.
İkinci örnekte ise not_durum fonksiyonundan çıkan veriler string. bool(‘F’) gibi bir kod True değerini verecektir. Bu nedenle sözlük değerleri ekrana basılmaktadır. (PC başında olmadığım için deneme yapamadım.)

1 Beğeni

Çünkü harf bastırılması ile ilgili bir işlem tanımlanmamış.

def not_durum(n):
    if n in range(0,50): return 'F'
    if n in range(50, 70): return 'D'
    if n in range(70, 80): return 'C'
    if n in range(80, 90): return 'B'
    if n in range(90, 101): return 'A

Yukarıdaki fonksiyon filter ile kullanıldığında şöyle bir fonksiyon gibi davranıyor.

def not_durum(n):
    return n

notlar.values()'u bu n’e göre sıralıyorsunuz. Ve harfleri bastırmıyor. return kısmına harf yerine başka birşey yazsanız onları da bastırmaz. Dolayısıyla harf bastırmak istiyorsanız, onun için ayrı bir fonksiyon tanımlamanız lazım. İsterseniz aşağıdaki kodları bir inceleyin.

notlar = {
    'Ahmet': 60,
    'Sinan': 50,
    'Mehmet': 45,
    'Ceren': 87,
    'Selen': 99,
    'Cem': 98,
    'Can': 51,
    'Kezban': 100,
    'Hakan': 66,
    'Mahmut': 80
}


def suzgec():
    """def f(n):
        return n
    return [i for i in filter(f, notlar.values())]"""
    # suzgec() fonksiyonunun içine sadece aşağıdakini de yazabiliriz.
    return notlar.values()
    # Bir üst satırdaki return'un geri dönderdiği değerler ile,
    # yukarıdaki f(n) fonksiyonunun geri dönderdiği değerler aynıdır.
    # Çünkü notlar.values()'un tamamı üzerinde işlem yapılıyor.


def harfe_cevir():
    for i in suzgec():
    # for i in notlar.values():
    # Yukarıdaki suzgec() fonksiyonuna gerek de yok aslında.
        if i in range(0, 50):
            yield "F"
        elif i in range(50, 70):
            yield "D"
        elif i in range(70, 80):
            yield "C"
        elif i in range(80, 90):
            yield "B"
        elif i in range(90, 100):
            yield "A"


if __name__ == "__main__":
    sonuc = harfe_cevir()
    print(*sonuc)

teşekkürler. Bana yeten cevabı aldım. Ama yazdığınız kodların bir kısmını anlayacak kadar bilgim henüz yok.

Acaba harfe_cevir fonksiyonundaki yield ifadelerini mi anlamadınız?

Mesela aşağıdaki kodla, bütün i’leri kullanamayız. Sadece ilk i değeri kullanılır.

def f(n):
    for i in range(n):
        return i

Bütün i’leri kullanabilmek için iki farklı yazım şekli var.

Birincisi:

def f(n):
    return [i for i in range(n)]


print(*f(10))

İkincisinde ise yield kullanılır:

def f(n):
    for i in range(n):
        yield i


print(*f(10))

yield, aşağıdaki gibi de kullanılır:

def f():
    for i in range(10):
        yield i


if __name__ == "__main__":
    x = f()

    # print(x.__next__())
    print(next(x)) # 0
    # print(x.__next__())
    print(next(x)) # 1
def f(n):
    for i in range(n):
        return i

neden olmuyor ? fonksiyonlar konusunu daha bitirmedim. O yüzden şuan çorba oldu kafam

Çünkü return dedikten sonra döngüye tekrar dönmüyor ilk değeri geri dönderiyor.

Demekki bende bu return olayı tam oturmamış. Neyse teşekkürler

Mesela aşağıda yazdığınız kodlarda return’ü doğru bir şekilde kullanmışsınız:

def suzgec(n):
    return n >= 70

Ama bu yöntemi bir döngü içerisinde uygulayamazsınız.
Bunun için return yerine yield kullanmak gerekir.

Yield ile ilgili lütfen aşağıdaki örneği de inceleyin.

def f():
    yield "hello"
    yield 1
    yield [i for i in range(10)]


x = f()

print(next(x))  # hello'yu bastırır.
print(next(x))  # 1'i bastırır.
print(next(x))  # [i for i in range(10)]'u bastırır.
# Şayet bir kez daha print(next(x)) yazarsak bu kez hata alırız
print(next(x))  # StopIteration
def not_durum(n):
        if n in range(0,50): return 'F'
        if n in range(50, 70): return 'D'
        if n in range(70, 80): return 'C'
        if n in range(80, 90): return 'B'
        if n in range(90, 101):return 'A'

print(not_durum(55)) #yazınca D yazıyor.

print(*filter(not_durum, notlar.values()))

burada sözlük değerlerini tek tek neden girmiyor. Demişsiniz ki

“Çünkü harf bastırılması ile ilgili bir işlem tanımlanmamış.”

Ben de not_durum() fonksiyonun içinde print(‘harf’) kodunu yazdım.

Bu sefer de aynı harften iki tane yazmaya başladı. retun’u silsem print (*filter()…) print fonksiyonu None hatası verecek. Sonra siz sınıflara falan girmişsiniz. Sonra olay çorba oldu. Dediğim gibi toparlamam gerek.

return “C” yerine print(“C”) yazarsanız bu sefer harfleri bastırır. Her not için bastırır. Yani notlar isimli sözlüğün içinde 3 tane 90 ile 101 arasında not alan kişi var. Dolayısıyla 3 tane A bastırılır. Ayrıca sınıflarla ilgili bir çalışma yapmadım.

Sizin yazdığınız kodlar:

notlar = {
    'Ahmet': 60,
    'Sinan': 50,
    'Mehmet': 45,
    'Ceren': 87,
    'Selen': 99,
    'Cem': 98,
    'Can': 51,
    'Kezban': 100,
    'Hakan': 66,
    'Mahmut': 80
}


def not_durum(n):
    if n in range(0, 50): print('F')
    if n in range(50, 70): print('D')
    if n in range(70, 80): print('C')
    if n in range(80, 90): print('B')
    if n in range(90, 101): print('A')


print(*filter(not_durum, notlar.values()))

Benim yazdığım da sizinkine benzer bir işlem yapıyor, sadece yol biraz farklı:

notlar = {
    'Ahmet': 60,
    'Sinan': 50,
    'Mehmet': 45,
    'Ceren': 87,
    'Selen': 99,
    'Cem': 98,
    'Can': 51,
    'Kezban': 100,
    'Hakan': 66,
    'Mahmut': 80
}


def harfe_cevir():
    for i in notlar.values():
        if i in range(0, 50):
            yield "F"
        elif i in range(50, 70):
            yield "D"
        elif i in range(70, 80):
            yield "C"
        elif i in range(80, 90):
            yield "B"
        elif i in range(90, 101):
            yield "A"


sonuc = harfe_cevir()
print(*sonuc)

İşte bu sefer de

print(not_durum(55))

D
None

Yazıyor. Çünkü print’le kullandım
Yani gömülü bir len() fonksiyonu gibi çalışmıyor. Öyle çalışması için return lazım. O zaman da baştaki sorun hasıl oluyor.

Dediğim gibi daha konuyu bitirmedim. Aşağıdaki yazdığınız sınıflara giriyor sandım. Bilmiyorum.
if __name__ == "__main__":

yapısını da bilmiyorum henüz. Kitapta gömülü fonksiyonlar konusu filter() de kaldım.

print(not_durum(55)) yerine not_durum(55) yazın. Çünkü zaten not_durum() fonksiyonunun içinde print() var, not_durum’u çağırdığınızda 55’e karşılık gelen harf notu bastırılacak.

Onu anlıyorum zaten sebebini. Ama ben yazdığım bir fonksiyonun Python’daki gömülü fonksiyonlar gibi çalışmasını istediğimden return kullanıyorum. Yani şimdilik bu kadar biliyorum.

Yapmak istediğinizi anlamaya çalışıyorum. Sizin yazdığınız kodlardaki filter() fonksiyonu ekrana harf bastırılmasına engel oluyor. Yani belki biraz kurcalanırsa, onunla da yapılır ama şimdiki haliyle print(“C”) yerine return “C” yazarsanız, rakamları geri döndermiş olursunuz.

Sizin yapmak istediğinize benzer bir şeyi başka bir yöntemle yapabiliriz:

notlar = {
    'Ahmet': 60,
    'Sinan': 50,
    'Mehmet': 45,
    'Ceren': 87,
    'Selen': 99,
    'Cem': 98,
    'Can': 51,
    'Kezban': 100,
    'Hakan': 66,
    'Mahmut': 80}


def harfe_cevir():
    listeye_al = [[] for _ in "FDCBA"]
    for i in notlar.values():
        if i in range(0, 50):
            listeye_al[0].append("F")
        elif i in range(50, 70):
            listeye_al[1].append("D")
        elif i in range(70, 80):
            listeye_al[2].append("C")
        elif i in range(80, 90):
            listeye_al[3].append("B")
        elif i in range(90, 101):
            listeye_al[4].append("A")
    return [j for i in listeye_al for j in i]


sonuc = harfe_cevir()
print(*sonuc)

Neyse. Fonksiyonlar konusunu tamamen bitireyim. Hala soru kalırsa sorarım.
Yardımlarınız için teşekkür ederim.

Bu da istediğiniz gibi olmadı sanırım. Siz hem not_durum(55) yazınca harfi return etmesini, hem de o sözlükteki notların da harf karşılıklarını return etmesini, daha sonra print() ile ekrana bastırılabilir olmalarını istiyorsunuz değil mi? Yani şu yapı korunsun. Ve aynı zamanda notlar’a da uygulanabilsin.

def not_durum(n):
    if n in range(0, 50):
        return "F"
    elif n in range(50, 70):
        return "D"
    elif n in range(70, 80):
        return "C"
    elif n in range(80, 90):
        return "B"
    elif n in range(90, 101):
        return "A"

@Orion
Lütfen aşağıdaki kodları bir inceleyin.

notlar = {
    'Ahmet': 60,
    'Sinan': 50,
    'Mehmet': 45,
    'Ceren': 87,
    'Selen': 99,
    'Cem': 98,
    'Can': 51,
    'Kezban': 100,
    'Hakan': 66,
    'Mahmut': 80
}


def not_durum(n):
    """Bu fonksiyon gömülü bir fonksiyon gibi kullanılabilir."""
    if n in range(0, 50):
        return "F"
    elif n in range(50, 70):
        return "D"
    elif n in range(70, 80):
        return "C"
    elif n in range(80, 90):
        return "B"
    elif n in range(90, 101):
        return "A"


def veri_gruplari_icin_not_durumu(veriler):
    """Yukarıdaki not_durum fonksiyonunu; 
    liste, demet gibi veri tipleri içindeki
    her sayı verisi için çağırır ve sonucu liste olarak
    geri gönderir.
    Bu da gömülü bir fonksiyon gibi kullanılabilir."""
    return [not_durum(n=i) for i in veriler]


print(*veri_gruplari_icin_not_durumu(veriler=notlar.values()))
# Örneğin veri grubu aşağıdaki gibi gruplar da olabilir.
# print(*veri_gruplari_icin_not_durumu(veriler=[i for i in range(10)]))
# print(*veri_gruplari_icin_not_durumu(veriler=(11, 45, 88)))
print(not_durum(55))

Vakit ayırdığınız için teşekkür ederim. Sonuçta ikinci bir fonksiyon tanımlayarak filter() de kullanabiliyoruz.