Python İleri Düzey Fonksiyonlar
Merhaba bu konuyu daha iyi kavraya bilmemiz için bir önceki konu olan python gömülü fonksiyonları gözden geçiriniz. Gömülü fonksiyonlardan sonra python’da fonsiyonlar konusu daha da ilerleteceğiz. İlk olarak lambda’yı inceleyeceğiz.
Python Lambda Kullanımı
Lamda ifadesi fonskiyon tanımlamak için kullanılmaktadır. Peki def
ifadesine ne oldu diyeceksiniz. Tabi bir şey olmadı
def
ifadesinu uzun soluklu fonksiyon tanımlamalarında kullanacağız, Lambda
ise tek satırda yazamamız gereken fonsiyonlarda kulllanacağız
. Anlaşıldığı üzere bu fonskiyon daha pratik bir şekilde fonksiyon tanımlamak için kullanılmaktadır. Aynı zamanda bazı durumlarda parametre yerine anlık fonksiyon tanımlamanız
gerekecektir. yani fonksiyon(param1,param2) şeklinde tanımlama esnasında parametre verdiğimiz alana def
ile fonksiyon tanımlayamazsınız ama Lambda
ile
tanımlayabilirsiniz. Şimdi bir tane iki sayıyı toplayan bir fonksiyon yazalım.
1 2 3 4 5 6 7 8 | def topla(param1,param2): return param1+param2; print(topla(3,3)) ###################Ekran Çıktısı########################### #6 ###################Ekran Çıktısı########################### |
Şimdi yukarıta tanımlamış olduğumuz fonksiyonu lambda ile tanımlayalım.
1 2 3 4 5 6 7 | topla=lambda param1,param2:param1+param2 print(topla(3,3)) ###################Ekran Çıktısı########################### #6 ###################Ekran Çıktısı########################### |
Anlaşılacağı gibi ikinci örneğimizde lambda ile yapmış olduğumuz tanımlama daha kolay.
Lambda tanımlamalarını şimdi bir sayının, verilen bir değer tam olarak bölünüp bölümendiğini yapan bir fonksiyon tanımlayalım.
1 2 3 4 5 6 7 | modAl=lambda param1,param2:param1%param2==0 print(modAl(33,3)) ###################Ekran Çıktısı########################### #True ###################Ekran Çıktısı########################### |
Şimdi lambda ile kdv’li fiyat hesaplayan programı yazalım.
1 2 3 4 5 6 | kdvHesap=lambda fiyat,kdvOrani:fiyat+(fiyat*kdvOrani) print(kdvHesap(100,0.08)) ###################Ekran Çıktısı########################### #108.0 ###################Ekran Çıktısı########################### |
Örneğimizi geliştirelim bir liste halinde verilen fiyatların kdv’lerini hesaplayalım.
1 2 3 4 5 6 | listeFiyat=[100,200,300,400] print(*map(lambda fiyat:fiyat+(fiyat*0.08),listeFiyat)) ###################Ekran Çıktısı########################### #108.0 216.0 324.0 432.0 ###################Ekran Çıktısı########################### |
Lambda kullanımının en önemli yanı burası. Yani bir fonsiyona parametre olarak yeni bir fonksiyon tanımlayabilmekteyiz.
İsterseniz yukarıdaki lambda
ile tanımlamış olduğumuz fonsiyonu def
ile kullanalım.
1 2 3 4 5 6 7 8 | listeFiyat=[100,200,300,400] def kdvHesap(fiyat): return fiyat+(fiyat*0.08) print(*map(kdvHesap,listeFiyat)) ###################Ekran Çıktısı########################### #108.0 216.0 324.0 432.0 ###################Ekran Çıktısı########################### |
İsterseniz bir de self link yapma fonksiyonu yapalım. Yani türkçe olarak belirlenen başlıklar url uygun hale getirmek için bir lambda yazalım.
1 2 3 4 5 6 | selfLink=lambda sozcuk:"".join([list("abccdefgghıijklmnooprsstuuvyz-")[list("abcçdefgğhıijklmnoöprsştuüvyz ").index(i)] for i in sozcuk]) print(selfLink( "çağlar bostanci ile python öğreniyorum")) ###################Ekran Çıktısı########################### #caglar-bostanci-ile-python-ogreniyorum ###################Ekran Çıktısı########################### |
İlk başkışta yukarıdaki fonksiyon anlaşılmaz gibi dursada aslında basit. Aşağıda def ile yazılmış halini yukarıdaki ile karşılatırınız.
1 2 3 4 5 6 7 8 9 10 11 | def selfLink(sozcuk,selfAlfabe=list("abccdefgghıijklmnooprsstuuvyz-"),alfabe=list("abcçdefgğhıijklmnoöprsştuüvyz ")): metin=""; for i in sozcuk: metin+=selfAlfabe[alfabe.index(i)] return metin; print(selfLink("çağlar bostanci ile python öğreniyorum")) ###################Ekran Çıktısı########################### #caglar-bostanci-ile-python-ogreniyorum ###################Ekran Çıktısı########################### |
Lamda kullanımını bir örnek daha verelim. Bu örneğimizde belirtilen rakam uzunluğunda şifre oluşturan bir fonskiyon yapalım.
1 2 3 4 5 6 7 8 9 10 | def randPass(num): import string as st karakter="".join([st.ascii_uppercase,st.ascii_lowercase,st.digits,st.punctuation]) cek=lambda x: random.choice(x) for i in range(num): yield cek(karakter) print("".join(randPass(10))) #######EKRAN ÇIKTISI########## #pxL&gu1LVN |
Özyinelemeli (Recursive) Fonksiyonlar
Öz yinelemeli fonksiyonlar bütün yazılım dillerinde var. Yani bir fonksiyonu özyilemeli hale getirebilirsiniz. Özyinelemeli fonksiyonların, normal fonksiyonlardan farkı birkez çalıştırıldıktan sonra tekrar tekrar kendini çağırıyor olmasıdır. Şimdi örnek olarak normal bir foksiyon yazalım.
1 2 3 4 5 6 7 8 9 10 11 | def karsilama(kisiSayisi=1): for i in range(kisiSayisi): print("Merhaba") karsilama(3) ###################Ekran Çıktısı########################### #Merhaba #Merhaba #Merhaba ###################Ekran Çıktısı########################### |
Yukarıdaki fonksiyon gönderilen kişi saysı kadar ekrana merhaba yazmaktadır. Bu fonksiyonu özyinelmeli olarak tasarlaryalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def karsilama(kisiSayisi=1): if kisiSayisi <=1: print("Merhaba") else: print("Merhaba") karsilama(kisiSayisi-1) karsilama(3) ###################Ekran Çıktısı########################### #Merhaba #Merhaba #Merhaba ###################Ekran Çıktısı########################### |
Dikkat ederseniz öz yinelemeli fonksiyonumuzda for
kullanmadık. Öncelikle gelen değerin 1’den küçük ve eşit olduğunun
kontrolünü yapıyor. Eğer değer bir ve küçükse sadece “merhaba” yadırıyoruz. Eğer değer birden büyükse ekrana “merhaba” yazdırıyoruz ve tekrardan
fonksiyonumuzu kisiSayısı değerini -1 düşürerek tekrar çağırıyoruz. Bu kullanıma özyinelemeli fonksiyon denmektedir.
Örnekleri çoğaltarak devam edelim. Şimdi yazılan bir mentini bir eksilterek ekrana yazalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | def yinele(deger): if len(deger) < 1: return deger else: print(deger) return yinele(deger[1:]) yinele("PYTHON") ###################Ekran Çıktısı########################### #PYTHON #YTHON #THON #HON #ON #N ###################Ekran Çıktısı########################### |
Bu fonksiyonu terten yazdıralım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | def yinele(deger): if len(deger) < 1: return deger else: print(deger) return yinele(deger[:-1]) yinele("PYTHON") ###################Ekran Çıktısı########################### #PYTHON #PYTHO #PYTH #PYT #PY #P ###################Ekran Çıktısı########################### |
Yukarıdan aşağı tersten yazdıralım
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | def yinele(deger): if len(deger) < 1: return deger else: print(deger[-1]) return yinele(deger[:-1]) yinele("PYTHON") ###################Ekran Çıktısı########################### #N #O #H #T #Y #P ###################Ekran Çıktısı########################### |
Öz yinelemeli fonksiyonları veritabanından gelen verilerde genel olarak kullanmaktayız. ilerleyen zamanlarda daha da örneklerini göreceğiz.
İç İçe (Nested) Fonksiyonlar
Python nested fonksiyonlar dediğimizde içe içe yazılan fonksiyonlar aklımıza gelmelidir. Kullanımı ve tanımlaması basittir. Şimdi örnek bir tane tanımlayalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def cikti(): def p(mesaj): print(mesaj) return p fnk=cikti() fnk("Merhaba Python") print("Değişken tipi : {}\nDeğiken id: {}".format(type(fnk),id(fnk))) ###################Ekran Çıktısı########################### #Merhaba Python #Değişken tipi : <class 'function'> #Değiken id: 2166099191984 ###################Ekran Çıktısı########################### |
1 2 | >>> fnk <function cikti.<locals>.p at 0x00000258A41AA8B0> |
Yukarıdaki kodlarda ilk olarak cikti() fonksiyonunu tanımladık daha sonra bu fonksiyon bize kendi içinde tanımlanmış olan p() fonksiyonunu geri dönderdi. Gelen p() fonsiyonunu fnk adında bir değikene atadık ve bu sayede fnk(“Merhaba Python”) dediğimizde p() fonksiyonu çalışmış ve ekrana vermiş olduğumu mesajı basmıştır.
Bu sayede ne yapmış olduk? Dikkat ederseniz fonksiyonu değişkene aldık bu sayede tanımlanmış olduğumuz p() fonksiyonunu farklı değişkenlerde ve farklı değerler tanımlayabileceğimiz anlamına geliyor. Aynı zamanda burada cikti() fonksiyonumuz bizim kapsayıcı fonksiyon ve içerisinde oluşturduğumuz p() ise iç fonksiyonumuz olmaktadır. fnk değişken tipini ekrana bastığımızda local çıktısnı alacağız. Bu durum cikti() fonksiyonu içerisinde yerel olarak tanımlanan p() fonsiyonu olduğunu göstermektedir.
Dikkat etmemiz gereken diğer bir kavramsa nonlocal tanımlamasıdır. Kapsayıcı içerisinde kullandığımız değişkenler ile iç fonksiyon içerisinde tanımlanan değişkenler farklıdır. Kapsayıcı fonksiyondan kullandığımız değişken global gibi davranmakta iç fonsiyonlardaki değişkenlerse localk değişkenlerdir. Bunu bir örnek ile pekiştirelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 | def kapsayici(): degisken="kapsayici değişken çalıştı." def icfonk(): degisken="local değişken çalıştı" print(degisken) return icfonk() fnk=kapsayici() ###################Ekran Çıktısı########################### #local değişken çalıştı ###################Ekran Çıktısı########################### |
Anlaşılacağı gibi değişken isimleri aynı olmasına rağmen fosksiyon içerisindeki yerel değişken çalışmıştır. Yine eğer istersek global olarak tanımlanan
değişkenleride aşağıdak gibi global
nanımlaması ile çalıştırabiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | mesaj="Global değişken" def kapsayici(): def icfonk(): global mesaj print(mesaj) return icfonk() fnk=kapsayici() ###################Ekran Çıktısı########################### #Global değişken ###################Ekran Çıktısı########################### |
Kapsayici fonsiyonu içerisindeki değikenleri local iç değişkenlerde de kullanmak istersen nonlocal
deyimi kullanılmaktadır. Bu örneklerle pekiştirelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | mesaj="Global değişken" def kapsayici(): kapsayici=1 def icfonk(): nonlocal kapsayici kapsayici+=1 print(kapsayici) return icfonk() fnk=kapsayici() ###################Ekran Çıktısı########################### #2 ###################Ekran Çıktısı########################### |
Yine örneğimizi artıralım. Kapsayici değişken üzerinden gönderdiğimiz değer iç fonsksiyonlarda kullanalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | def dType(degisken): def tipi(): return type(degisken) def uzunluk(): return len(degisken) def ekle(): nonlocal degisken return "=>"+degisken+"<=" def cikti(): print("Değişken : {}\nDeğiken tipi : {}\nDeğiken uzunluğu : {}".format(ekle(),tipi(),uzunluk())) return cikti() fnk=dType("PYTHON") ###################Ekran Çıktısı########################### #Değişken : =>PYTHON<= #Değiken tipi : <class 'str'> #Değiken uzunluğu : 6 ###################Ekran Çıktısı########################### |
Kapsayıcı değişkenimizdeki gelen değişkeni ekle() fonksiyonumuzda güncellendik. Tabi güncelleme yapabilmemiz için nonlocal
olarak tanımlamalıyız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | def sayac(): sayi=0 def artir(): nonlocal sayi sayi+=1 return sayi return artir fnk=sayac() print(fnk()) print(fnk()) print(fnk()) print(fnk()) ###################Ekran Çıktısı########################### #1 #2 #3 #4 ###################Ekran Çıktısı########################### |
Anlaşılacağı gibi fonksiyon içerisine belirlemiş olduğumuz değer fonksiyon çalıştıktan sonra kaybolmuyor ve her artır dediğimizde bir atırıyor.
Python Üreteçler
Üreteç ile ilgili ilk örneklerimizi list konusunu işleken vermiştik. Yine hatırlatma adına bir örnek yapalım.
1 2 3 4 5 6 7 | liste=[i for i in range(10) ] print(liste) ###################Ekran Çıktısı########################### #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ###################Ekran Çıktısı########################### |
Üreteçlerde en önemli gömülü fonksiyonlardan biri yield
foksiyonudur. Python ve diğer yazılım dillerinden oluşturlan fonsiyonlar
çalıştırıldıktan sonra return ile geriye değer dönderirir ve görevelerini tamamlarlar. Çalışan fonksiyon ve içerisindeki değişkenler ram’den silinir.
Yeild fonksiyonu ise aynı iç içe fonksiyonlarda kullandığımız gibi kaldığı yerden devam etmektedir. Bunu bir örnekle pekiştirelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | print("iç içe fonksiyon örneği") def sayac1(): sayac=0 def artir(): nonlocal sayac sayac+=1 return sayac return artir s1=sayac1() print(s1()) print(s1()) print(s1()) print("yield kullanımını") def sayac2(): sayi=0 while True: sayi+=1 yield sayi s2=sayac2() print(next(s2)) print(next(s2)) print(next(s2)) print(next(s2)) ###################Ekran Çıktısı########################### #iç içe fonksiyon örneği #i1 #i2 #i3 #iyield kullanımını #1 #2 #3 #4 ###################Ekran Çıktısı########################### |
Örnekte kullandığımız yield fonksiyonu şu işe yaramaktadır. Fonksiyo çalıştığında yield fonsiyonunu görünce durur ve sağındaki değişkenin döndürür. Sonra next fonsiyonu ise bir sonraki yield devam etmesi için tekrar harekete geçer diğer bir yield fonksiyonunu görünce durur. Bu hareketliliğin devamını next() fonksiyonu sağlamaktadır. Biz ise while döngüsünde sonsuz döngüyü sağlamak için direk True değerini veriyoruz. Bu sayede fonksiyon ne kadar çağırılırsa sayaç o kadar artırılmaktadır.
Bu fonksiyonu bir örnekle daha da pekiştirelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | def ornekFunc(): yield "Yield 1 çalıştı" yield "Yield 2 çalıştı" yield "Yield 3 çalıştı" fnk=ornekFunc() print(next(fnk)) print(next(fnk)) print(next(fnk)) print(next(fnk)) ###################Ekran Çıktısı########################### #iYield 1 çalıştı #iYield 2 çalıştı #iYield 3 çalıştı #iTraceback (most recent call last): #i File "C:\Users\webMaster\Desktop\python_document\calismalar\python-2.py", line 10, in <module> #i print(next(fnk)) #iStopIteration ###################Ekran Çıktısı########################### |
Yukarıdaki fonksiyon içerisinde üç kez yield kullandık. Üçkez next() fonksiyonunu kullandıktan sonra adım adım ilerledi ve dördüncü next() fonksiyonunda hata verdi bunun sebebi ise fonksiyonun sonuna gelinmiş olmasıdır.
Yine iç içe fonskiyon kullanımlarında da iç fonksiyon içerisindeki yield kullanımı için “yield from” tanımlaması yapılmaktadır. Bunu aşağıdaki örenklerle daha da detaylandıralım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def fonkIc(): yield "İc fonksiyon 1" yield "İc fonksiyon 2" def fonkDis(): yield "Dış fonksiyon 1" yield from fonkIc() yield "Dış fonksiyon 2" for i in fonkDis(): print(i) ###################Ekran Çıktısı########################### #iDış fonksiyon 1 #iİc fonksiyon 1 #iİc fonksiyon 2 #iDış fonksiyon 2 ###################Ekran Çıktısı########################### |
Dış fonksiyonu döngüye soktuğumuzda iç fonksiyondaki yield’lerin çalışması için yield from
kullanıldı.
Üreteçlere örnek olarak aşağıdaki koldlarada bakmanızı öneririm. Bu konu buraya kadar faydalı olması temennisiyle BAŞARILAR.
1 2 3 4 5 6 7 8 9 10 | liste=[i for i in range(10)] sozluk={"veri_"+str((i+1)):i for i in range(10)} print(liste) print(sozluk) ###################Ekran Çıktısı########################### #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] #[{'veri_1': 0, 'veri_2': 1, 'veri_3': 2, 'veri_4': 3, 'veri_5': 4, 'veri_6': 5, 'veri_7': 6, 'veri_8': 7, 'veri_9': 8, 'veri_10': 9} ###################Ekran Çıktısı########################### |