Fonksiyonlar

Fonksiyonlar, belli bir işi saklayabileceğiniz yapılardır. Örneğin bir hesap makinesi yapacağınızı düşünelim. Bu durumda her işlem için (toplama, çıkarma vb.) ayrı bir fonksiyon yazar, gerektiği yerde bu fonksiyonu çağırabilir ve içerisindeki işlemlerin çalışmasını sağlayabilirsiniz. Kısacası fonksiyonlar; belli bir işe yarayan yapılardır. Bir fonksiyona belli bir işi tanımlarsınız, sonrasında o işi tekrar tekrar başka yerlerde yazmak yerine sadece o fonksiyonu çağırırsınız ve işiniz hallolur. Bu, kodunuzun karmaşık olmasından sizi kurtarır.

Fonksiyonlar, okunabilir kod (readable code) yazmanızı sağlar. Bu sizin, kodunuzu okumak isteyen başka bir yazılım geliştiricinin kodunuzu daha iyi okuyup anlayabilmesini sağlar. Çünkü fonksiyonlar, belli bir işi parçalara ayırarak her parçayı özel olarak tutarlar. Bu sayede kodunuz üzerinde hâkimiyetiniz artar ve bakım maliyetiniz düşer.

Kodunuz içerisinde Zero Day gibi güvenlik açıkları çıktığı zaman bu açıkları kapatmanız daha kolay olacaktır. Çünkü güvenlik açığı size raporlandığı zaman problemin, kodun hangi kısmından kaynaklandığını daha rahat keşfeder ve ona göre bir müdahalede bulunursunuz.

Fonksiyonların en önemli avantajlarından biri 'verimlilik' sağlamasıdır. Normal değişkenler veya komutlar, sırası geldiğinde çalışır yani herhangi bir pasiflik durumu yoktur; hafızada sürekli olarak yer tutarlar. Bu durum, kodun verimliliğini düşürür ve maliyetini artırır. Fonksiyonlar ise onları tanımladığınızda pasif kod konumuna düşer ve ancak çalıştırıldıklarında (çağırıldıklarında) çalışırlar. Bu sayede verimlilik artar.

Şimdi, isterseniz ilk önce bir fonksiyonun Python'da nasıl tanımlandığına bakalım.

Bir fonksiyonu tanımlamak için ihtiyacımız olan anahtar kelime 'def'tir. Bu, İngilizce'deki 'defined' yani 'tanımlanmış' kelimesinden gelir.

def anahtar kelimesini verdikten sonra bu fonksiyona bir isim veriyoruz ve bir parantez çiftini oraya yerleştirip iki nokta üst üste koyuyoruz. print() veya input() fonksiyonlarını düşünün; genel olarak fonksiyonların bir işi olur ve bu fonksiyon isimlerinin yanına bir parantez eklenir. İşte, print veya input kadar kapsamlı bir fonksiyonumuz olmasa da bizim de selam() adında bir fonksiyonumuz var. Değişken tanımlama konusundan da bileceğiniz üzere fonksiyonların isimleri de o kurallara göre belirlenmelidir. Bunlar, bir işi tuttukları için isimlerinin açıklayıcı olması gerekir. Detaylar için şu blogu okuyabilirsiniz: Değişkenler

Şu an, 'selam' isimli fonksiyonumuzun yaptığı iş; ekrana bir şeyler yazdırmak. İsterseniz kodu çalıştırıp ne olacağına bakalım.

Neden çalışmadı? Daha doğrusu çalıştı ama neden ekrana 'Hello, Cyber Worm.' yazdırmadı? Bunun sebebi; deminden beri bahsettiğim 'çağırma' olayından kaynaklanıyor. Bu fonksiyonun çalışması için ilk önce bunu çağırmamız lazım. Fonksiyonlar karakterli yapılardır; çağırılmadıkları ortama girmezler. Peki, bu çağırma işlemini nasıl yaparız?

Gördüğünüz gibi sadece fonksiyonun ismini yazdım ve bir parantez ekledim; fonksiyonu çağırmış oldum. Kodu tekrar çalıştırdığımda fonksiyonumuzun gerçekten de işini yaptığını görüyoruz. Birden fazla kez çağırırsak ne olur? Diyelim ki ben 4-5 farklı yerde bu fonksiyonu kullanacağım; ne olacak?

Elbette, hiçbir şey olmayacak. Fonksiyonları istediğiniz yerde ve istediğiniz kadar çalıştırabilirsiniz. İsterseniz işin içine biraz aksiyon katalım ve selamlayacağımız kişinin ismini kullanıcıdan alalım.

Gördüğünüz gibi; fonksiyonumuz her ne kadar basit bir iş yapıyor olsa da aslında çok daha etkili ve verimli bir hâle geldi. Bu noktada elbette, name bilgisini fonksiyonun içine de tanımlayabilirsiniz. Bu, sizin kodunuzun yapısına bağlı olarak değişecektir.

Fonksiyonlarda Parametreler

Lütfen bu kısımda sakin olmaya çalışın ve blogun sonunda her şeyi eksiksiz olarak tekrar edin, uygulayın. Son olarak; lütfen kendi pratiklerinizi yapın.

Fonksiyonlar, aslında o kadar da basit yapılar değildir. Fonksiyonlara bir de parametre verme olayımız var. Bu parametreler, fonksiyon isminin yanındaki parantezler içerisine verilir. Ancak parametre dediğim için gözünüz korkmasın; bildiğiniz değişken tanımlaması yapıyoruz. Bir fonksiyona parametre verdiğimiz zaman o fonksiyon parametresini almadan -onu çağırsanız bile- çalışmaz. Önce bir parametrenin neye benzediğini görelim.

Biraz önce name = input... olarak tanımladığımız değişkeni bu sefer parametre olarak fonksiyona verdim. Bu sayede aslında dolaylı olarak input istemiş oluyoruz. Ancak bu input'tan kullanıcının haberi olmayacaktır ve parametreli fonksiyonları dizayn ederken bu noktaya dikkat etmeniz gerekir. Ne demek istiyorum?

Şimdi, ben parametreli bir fonksiyon tanımladım ve bu parametre 'name' adında. Kullanıcı eğer name parametresini karşılayacak bir girdi girmezse bu kod çalışmayacaktır. Biraz önce dediğim gibi; 'çağırsanız bile çalışmaz'. Bakalım.

Gördüğünüz gibi hata aldık. Mesaj bize şunu diyor: "Gerekli olan bir argüman eksik". Demek ki argümanı yani parametreyi tanımlamak yetmiyormuş. O zaman bu sorunu nasıl çözebileceğimize bakalım.

Fonksiyonun çalışması için fonksiyonu nasıl çağırıyorsak; parametresi olan bir fonksiyonu çağırırken de bu parametreyi karşılayacak değeri vermemiz gerekir. Bu noktada selam(...) içerisine ne verirseniz verin 'name' parametresi yerine geçecektir.

Aklınıza şöyle bir soru gelebilir: "Madem parametreyi karşılayacak değeri vermem lazım, o zaman parametre tanımlamak yerine direkt olarak fonksiyonun içinden girdi alırım; olmaz mı?". Elbette, olur. Ancak bu kullanıma ihtiyacınız olacağını bilin istiyorum. Kullanıcıdan girdi almak yerine aslında fonksiyonun 'sizin istediğiniz şekilde' çalışması için bu kullanımı sağlayabilirsiniz; hâkimiyet tamamen sizde.

Peki, birden fazla parametre olursa o zaman ne olur?

Bu sefer de hepsine bir değer vererek çağırmanız gerekir. Eğer bir tanesi bile eksik olursa o zaman hata alacaksınızdır. Ayrıca çıktıya dikkat edelim; bu bir Tuple değil mi? Parametrelerin ne kadar önemli ve güvenli bir işlev olduğunu görüyorsunuz.

Normal şartlarda yukarıdaki gibi 4 parametresi olan bir fonksiyon çağırılırken, yukarıdakinin aksine şöyle çağırılır:

selam("Cyber", "Worm", 23, "NetworkSec")

Yani hangi değerin hangi değişkene ait olduğunu belirtmeden sırasıyla yazılır; Python ise bunu anlar. İlk olarak verilen değerin ilk parametreye ait, ikincisinin de ikinci parametreye ait olduğunu anlar. Ancak her zaman dediğimiz gibi; 'okunabilir kod'. Bunu, yukarıdaki gibi yazarsanız hem daha keskin bir kontrol sağlamış olursunuz hem de daha okunabilir bir kod yazmış olursunuz.

Devam edelim.

Bu noktada, parametre vermeden de input alabiliriz; bunu, fonksiyonun içinden istiyorum. Peki, madem fonksiyonu çağırırken 'name="Cyber"' tarzında bir çağırma işlemi yapabiliyoruz; o zaman neden fonksiyonun içinden input almak yerine o input'u fonksiyonu çağırırken almıyoruz? Nasıl yani?

Yukarıdaki kullanım; daha pratik bir input alma işlemi. Ancak bu, pek fazla input almanızı gerektirmeyen durumlarda daha uygun olacaktır.

Fonksiyona verdiğiniz argümanın değerini varsayılan olacak şekilde ayarlayabilirsiniz. Aslında bu, fonksiyonu çağırırken verdiğiniz değer ile aynı mantıktadır. Yani yukarıdaki gösterim ile 'selam("Cyber")' aynı şeyi ifade eder.

Şimdi bir özet geçelim.

Fonksiyonlar, belli bir işi yapan parçacıklardır; argümansız da argümanlı da olabilirler. Bu noktada argümanlı bir fonksiyon tanımlanırsa, çağırılması esnasında o argümanla eşleşecek bir değerin verilmesi gerekir.

Argümanlı bir fonksiyonu çağırırken verdiğiniz değeri eliniz ile girdiyseniz (selam("Cyber Worm") şeklinde) bu, hâkimiyetin tamamen sizde olduğunu gösterir ve fonksiyon, verdiğiniz parametrenin dışında bir değer döndürmez.

Argümanı, fonksiyonu çağırırken input olarak alıyorsanız bu durum, fonksiyonun argümanının kullanıcı tarafından verildiğini gösterir (selam(name=input("Name: ")) gibi).

Fonksiyona verdiğiniz argümanlar/parametreler, varsayılan değer alabilir (selam(name="Cyber") gibi). Bu noktada fonksiyonu çağırırken fonksiyonun içine argüman değeri vermenize gerek yoktur. Zaten varsayılan olarak verildiği için sorun olmayacaktır.

pass

Bu komutun anlamı 'geç' şeklindedir. Bunu 'continue' komutuna da benzetebilirsiniz. Bu komutu daha çok, tanımladığımız ama henüz kullanmak istemediğimiz fonksiyonlar için kullanıyoruz.

Gördüğünüz gibi, fonksiyonu tanımladım ama şu an içine herhangi bir şey yazmak istemiyorum; pass komutunu veriyorum ve yoluma bakıyorum. Bu noktada fonksiyon içerisine herhangi bir şey yazmadan bırakırsanız hata alırsınız:

Bu komut aynı zamanda; "hiçbir şey yapmadan devam et" anlamına gelir. Bu komutu continue komutuna benzetebileceğinizi söylemiştim ama aradaki en keskin fark; "continue komutu atlama yaparken pass komutu hiçbir şey yapmamayı sağlar". Ne demek istiyorum?

Yukarıdaki kodun ne yaptığını artık çok iyi biliyorsunuz o yüzden bunu açıklamayacağım. Ancak ben, bilerek elif kısmının çalışmasını sağladım ve gördüğünüz gibi ekranda hiçbir çıktı almadım çünkü pass komutunu verdim ve Python bunu gördüğünde direkt olarak hiçbir şey yapmadan bu kısmı geçti.


Yayınlanma Tarihi: 2022-11-01 18:37:55

Son Düzenleme Tarihi: 2022-11-07 16:57:04