python toplama fonksiyonu / Python Fonksiyonlar (def) | 1Kodum

Python Toplama Fonksiyonu

python toplama fonksiyonu

Python Fonksiyonlar

Merhaba arkadaşlar,

seafoodplus.info da Python Dersleri serisinin bir dersinde yine beraberiz. Bu derste Python Fonksiyon konusunu işleyeceğiz. Bu yazıda Fonksiyonların ne olduğunu ne işe yaradığını,  nasıl kullanıldığını ve fonksiyon tiplerini baştan sona ele alacağım. Hadi o zaman başlayalım 🙂

Fonksiyon Nedir?

Python Eğitim serisinin ilk dersinden beri hep fonksiyon kavramını kullandık. Dilerseniz kafanızı çok karıştırmadan fonksiyon kavramını kısaca tanımlayayım.

Fonksiyonlar kısaca belirli bir işlevi yapmak için oluşturulan komutlar kümesidir. Örneğin print() fonksiyonu ekrana çıktı vermemizi sağlayan işlevi yapmak için belirli komutlar bulundurur.

Neden Fonksiyonlar?

Şimdi sizin aklınıza şöyle bir şey gelmiştir ben fonksiyon kullanmasam olmaz mı? Tabi ki kullanmasanız da olur ama belli bir yerden sonra kod satırı arttığında karmaşıklık artıyor ve kontrol etmek zorlaşıyor. Onun için biz fonksiyonları kullanıyoruz.

Böylece biz yapmak istediğimiz işlevler için her seferinde kod yazmak yerine bir defa fonksiyon oluşturuyoruz işlem yapmak istediğimiz zaman çağırıp kullanıyoruz. Böylece fazla kod karmaşığından kurtuluyoruz.

Kısaca Fonksiyonlar;

  • Her biri belli bir işi yerine getiriyor.
  • Parametre alan fonksiyon var almayan fonksiyon olmak üzere iki ayırabiliriz.
  • Fonksiyonların görevi, karmaşık işlemleri bir araya toplayarak, bu işlemleri tek adımda yapmamızı sağlamaktır.
  • Fonksiyonları kullanarak, bir veya birkaç adımdan oluşan işlemleri tek bir isim altında toplayabiliriz.

Fonksiyonların ne olduğunu ve neden kullandığımızı biliyorsak arttık nasıl kullanacağımızı öğrenelim.

Fonksiyon Kullanımı

Python da iki tür fonksiyon vardır birincisi Python ile hazır gelen fonksiyonlar yani gömülü fonksiyonlar, ikincisi ise bizim oluşturduğumuz fonksiyonlar. Print() ve type() gibi fonksiyonlar Python ile birlikte geldiği için biz sadece onları kullanmak istediğimiz yerde çağırıyoruz.

Fonksiyonların genel kullanım taslağı şu şekildedir.

def fonksiyon_Adi(parametre1,parametre2):

            işlemler

fonksiyon_Adi()

Genel olarak taslağı gördük şimdi bir örnekle gösterelim bunun için. Ben bunun için hemen basit bir fonksiyon oluşturayım.

def  yazdir():     print("seafoodplus.info Python Dersleri")

Gördüğünüz gibi fonksiyonumuzu oluşturduk. Şimdi fonksiyonumuzu çağıralım bunun için fonksiyonun adını yazmamız yeterli kullanımı şu şekilde;

 Fonksiyon_Adi(parametre1,parametre2)

Bizim fonksiyonuz parametre almadığı için bizim bir şey yazmamıza gerek yok. Hemen çağıralım;

def yazdir():     print("seafoodplus.info Python Dersleri") yazdir() Çıktı: seafoodplus.info Python Dersleri

Bir defa çağırdığımız için bu işlevi bir defa yaptı biz kaç defa çağırırsak o kadar ekrana yazdırır.

def yazdir():     print("seafoodplus.info Python Dersleri") yazdir() yazdir() yazdir() Çıktı: seafoodplus.info Python Dersleri seafoodplus.info Python Dersleri seafoodplus.info Python Dersleri

Dilerseniz aynı fonksiyonu bide farklı şekilde yazalım. Burada return deyimini kullanacağım çünkü biz fonksiyonlarla sadece ekrana yazdırma işlemi değilde bize sonuç  döndürecek fonksiyonlarda yazacağız bu yüzden  return kullanacağız.

Return Deyimi

return deyimi fonksiyonun geriye herhangi bir değer döndürmesini sağlar.

def yazdir():     return "seafoodplus.info Python Dersleri" print(yazdir()) Çıktı: seafoodplus.info Python Dersleri

Bu şekilde fonksiyonun döndürdüğü değeri yazdırmış olduk.

Python da parametre almayan fonksiyonları öğrendik. Şimdi parametre alan ve geriye değer döndüren bir fonksiyon yazalım.

def toplama(sayi1,sayi2):    return sayi1+sayi2 print("Sonuç :",toplama(3,4))  Çıktı: Sonuç: 7

Bu şekilde girdiğimiz sayıların toplamını döndüren bir fonksiyon yazmış olduk.  Peki biz bu parametrelere önceden değer atayabilir miyiz tabi ki de hemen göstereyim;

 def toplama(sayi1=6,sayi2=8):    return sayi1+sayi2 print("Sonuç :",toplama()) Çıktı: Sonuç : 14

Gördüğünüz gibi parametrelere önceden değer ataya biliyoruz. Bu yüzden Fonksiyonu çağırdığımız zaman parametrelere değer vermemize gerek yok. Peki parametreye değer verirsek ne olur hemen değer verip deneyelim.

def toplama(sayi1=6,sayi2=8): return sayi1+sayi2 print("Sonuç :",toplama(4,3)) Sonuç : 7

Gördüğünüz gibi bize bu sefer 14 değil de 7 sonucunu geriye döndürdü. Yani eğer biz fonksiyonu çağırdığımız zaman değer vermezsek Python default olarak önceden parametrelere verdiğimiz değerleri atar.

Şuana kadar hep fonksiyon içinde parametrelere değer yani argüman verdik bide dışarıdan aldığımız değerler ile fonksiyonlarda işlem yapalım.

def toplama(sayi1,sayi2): return sayi1+sayi2 sayi1 = int(input("Birinci sayıyı girin :")) sayi2 = int(input("İkinci sayıyı girin :")) print("Sonuç :",toplama(sayi1,sayi2))  Çıktı: Birinci sayıyı girin İkinci sayıyı girin Sonuç : 61

Bunu da öğrendiğimize göre şimdi fonksiyonlarla bir hesap makinesi yapalım.

def toplama(sayi1,sayi2): return sayi1+sayi2 def cikarma(sayi1,sayi2): return sayi1-sayi2 def carpma(sayi1,sayi2): return sayi1*sayi2 def bolme(sayi1,sayi2): return sayi1/sayi2 while True: secim = input("Bir Seçim Yapın :") if secim == "q": exit() sayi1 = int(input("Birinci sayıyı girin :")) sayi2 = int(input("İkinci sayıyı girin :")) if secim=="1": print("Sonuç :", toplama(sayi1, sayi2)) elif secim =="2": print("Sonuç :", cikarma(sayi1,sayi2)) elif secim =="3": print("Sonuc :",carpma(sayi1,sayi2)) elif secim=="4": print("Sonuç :",bolme(sayi1,sayi2)) else: print("Yanlış seçim lütfen tekrar deneyin") exit() Çıktı: print("Sonuç :",toplama(sayi1,sayi2)) print(""" Toplama :1 Çıkarma :2 Çarpma  :3 Bölme   :4 Çıkış   :q """)

Return deyimini anlatmış olduk. Şimdi biz fonksiyonları tanımlarken istediğimiz yerde çağırıp kullandığımızı söylemiştik peki fonksiyonları başka bir fonksiyonun içinde çağırıp kullanabiliyoruz hemen gösterelim.

Fonksiyon İçinde Fonksiyon

Şimdi bu uygulamamızda Standart Sapma hesapla uygulaması yapacağız. Kısaca Standart Sapma anlatırsak. Standart sapma, bir serideki sayıların, serinin aritmetik ortalamasından farklarının karelerinin toplamının dizinin eleman sayısının bir eksiğine bölümünün kare köküdür.

Biraz açmak gerekirse, standart sapma hesaplamak için;

  • Sayıların aritmetik ortalaması hesaplanır.
  • Her bir sayının aritmetik ortalamadan farkı bulunur.
  • Bulunan farkların her birinin karesi hesaplanır.
  • Farkların kareleri toplanır.
  • Elde edilen toplam, serinin eleman sayısının bir eksiğine bölünür.
  • Bulunan sayının karekökü alınır.

Bizde bunun için önce serinin ortalamasını ortHesapla() fonksiyonu hesaplayacağız bulduğumuz sunucu return ile döndüreceğiz ve standartHesapla() fonksiyonunun da kullanacağız.

def ortHesapla(liste):     ort = sum(liste) / len(liste)     return ort def standartHesapla(liste):     standartKarekok=[]    for i in range(len(liste)):         seafoodplus.info((liste[i]-ortHesapla(liste))**2)     standartSapma = (sum(standartKarekok)/len(liste)-1)**     return  standartSapma liste = [22,23,20,14,32,2,40] print("Standart Sapma:",standartHesapla(liste)) Çıktı: Standart Sapma:

Fonksiyon içinde fonksiyon çağırıp kullanmayı öğrendik. Eminim aklınıza şöyle bir soru gelmiştir: Fonksiyonlar kendi kendini çağırabiliyor mu? Tabi ki yapabiliyor hatta buna fonksiyonlara bir isim bile verilmiş 🙂 Hadi o zaman başlığımızı atalım.

Recursive (Özyineli) Fonksiyonlar :

Recursive fonksiyonlar kendi kendini çağıran fonksiyonlardır. Kısaca bir döngü gibi düşünebiliriz burada dikkat etmemiz gereken şey sonsuz döngüye girmemesi için bir şart koşulu kullanmalıyız. Recursive fonksiyonlar genel olarak diğer fonksiyonlara göre karmaşıklığı arttırdığı için ve fazla bellek kullandığı için pek kullanmayı önermem ama işe yaradığı durumlarda vardır. Hemen bir örnekle göstereyim;

Bunun için fibonacci sayıların toplamını hesaplama uygulaması yapacağım.

Fibonacci dizisi, her sayının kendinden önceki  iki sayının   toplanması sonucu oluşan bir sayı dizisidir.

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55

def fibonacci(sayi): if sayi==0: return 0 if sayi==1: return 1 return fibonacci(sayi-1) + fibonacci(sayi-2) sayi=int(input("Bir sayi gir :")) print(fibonacci(sayi)) Çıktı: Bir sayi gir :8 21 # 8' kadar ki sayıların toplamı 21 eder

Resursive fonksiyonları da anlatmış oldum sisten isteğim tam olarak oturması için sizde faktoriyel hesaplama uygulamasını recursive fonksiyonu ile yapmanız eğer yapamazsanız soru-cevap kısmından yazmanız dilerseniz buradan da yardım alabilirsiniz.

seafoodplus.info da Python Dersleri serisinin bu dersinde Python Fonksiyonlar konusunu işledik. Bir sonraki derste Python da Fonksiyonların Kapsamı konusunu anlatacağıseafoodplus.infodığınız bir yer ve ya eksik yada yanlış gördüğünüz bir yer varsa iletişime geçmekten çekinmeyin.

Cahit İşleyen

Data Scientist at @seafoodplus.info
Python ve Linux sever.
Çay tiryakisi

Python Fonksiyonlar

Python Fonsiyonlar

Yazdığımız bir python uygulamasındaki belli bir kod parçasını bir kaç yerde kullanma ihtiyacı duyduğumuzda fonksiyon oluşturmak işlerimizi kolaylaştırır. Böyle durumlarda sürekli kullanacak olduğumuz kod satırlarını fonksiyonlar içine alıp istediğimiz zaman çağırıp çalıştırabiliriz.

Örneğin basit bir matematiksel işlem yapacağız ve bir çok yerde bu matematiksel işlemi tekrarlayacağız bu durumda bir fonksiyon oluşturup defalarca kullanabiliriz.

Ayrıca işin daha güzel yani Python da hazır bir çok kütüphane var ve bu kütüphaneler içinde önceden oluşturulmuş bir sürü fonksiyon mevcut. Çoğu zaman fonksiyonun içeriğini yazmak yerine hazır olanını kullanabileceğiz. Örneğin gönderdiğimiz bir sayının karakökünü alan sqrt() fonksiyonu.

Peki gelin Fonksiyon oluşturmaya başlayalım.

Fonksiyon Tanımlama

Fonksiyon tanımlamak için def komutunu kullanıyoruz.

Örnek

def hello(): print("Merhaba")

hello() isminde basit bir fonksiyon tanımladık ve artık fonksiyonumuz çalıştırılmayı bekliyor.

Fonksiyon Çağırma

Fonksiyonları tanımlıyoruz ancak çağrılmadıkça fonksiyon bloğu içerisindeki kodlar çalıştırılmaz. Fonksiyonu çağırmak için fonksiyonun ismi ile birlikte parantezleri kullanmalıyız.

Örnek

def hello(): print("Merhaba") hello() # Merhaba

Gördüğünüz gibi fonksiyon çağrıldığında ekrana Merhaba yazar. Fonksiyonu her çağırdığımızda kodlar tekrar çalıştırılacağından dolayı ekrana Merhaba yazmaya devam edecektir.

Örnek

hello() # Merhaba hello() # Merhaba hello() # Merhaba hello() # Merhaba

Fonksiyona Parametre Gönderme

Fonksiyonlara dışarıdan bilgi gönderip fonksiyon içerisinde kullanabiliriz.

Örnek

def hello(name): print("Merhaba "+ name) hello("Arda") # Merhaba Arda

Örnekte olduğu gibi dışarıdan name parametresini fonksiyona gönderip kullanabiliriz.

Fonksiyondan Geriye Bilgi Gönderme

Fonksiyon içerisinde print() ile bilgi yazdırmak yerine bilgiyi geriye de döndürebiliriz.

Örnek

def hello(name): return "Merhaba "+ name print(hello("Arda")) # Merhaba Arda

Gördüğünüz gibi print ile bilgiyi fonksiyon içerisinde yazdırmak yerine "Merhaba Arda" bilgisini fonksiyondan geriye return komutu ile döndürdük ve sonrasında bilgiyi ekrana yazdırdık.

Örnek

def toplama(a,b): return a+b sonuc = toplama(10,20) print(sonuc) # 30

toplama fonksiyonu dışarıdan a ve b parametrelerini bekler ve gönderdiğimiz değerleri fonksiyon içerisinde toplar ve sonucu 30 olarak geriye döndürür, sonrasında fonksiyondan gelen değeri sonuc değişkenine alabiliriz.

Fonksiyondan Fonksiyon Çağırma

Bazen tanımladığımız bir fonksiyonu başka bir fonksiyon içerisinde kullanmak isteyebiliriz.

Örnek

def yasHesapla(dogumYili):     return  - dogumYili ageCinar = yasHesapla() ageAda = yasHesapla() ageSena = yasHesapla() print(ageCinar, ageAda, ageSena)

Gördüğünüz gibi 3 kişi için yaş hesaplama işlemini tek bir yasHesapla fonksiyonu ile yapabildik. Eğer ki hesaplanan yaş bilgisine göre emekliğe kalan süre hesabını da hesaplamak istersek bu durumda başka bir fonksiyon kullanabiliriz.

def EmekliligeKacYilKaldi(dogumYili, isim): yas = yasHesapla(dogumYili) emeklilik = 65 - yas if emeklilik > 0: print(f'emekliliğinize {emeklilik} yıl kaldı') else: print('Zaten emekli oldunuz') EmekliligeKacYilKaldi(, 'Ali') EmekliligeKacYilKaldi(, 'Ahmet') EmekliligeKacYilKaldi(, 'Yağmur')

Ekran çıktısı;

Ali emekliliğinize 29 yıl kaldı Ahmet Zaten emekli oldunuz Yağmur emekliliğinize 20 yıl kaldı

Python Fonksiyon Örnekleri

1- Gönderilen bir kelimeyi belirtilen kez ekranda gösteren python fonksiyonunu yazınız.

def yazdir(kelime, adet):     print(kelime * adet) yazdir('Merhaba\n', 10)

Ekrana 10 kere Merhaba yazar. 

** \n bir alt satıra geçmek için kullanılır.

2- Gönderilen 2 sayı arasındaki tüm asal sayıları bulan python fonksiyon uygulamasını yapınız.

def asalSayılariBul(sayi1, sayi2):     for sayi in range(sayi1, sayi2+1):         if sayi > 1:             for i in range(2, sayi):                 if (sayi % i == 0):                     break             else:                 print(sayi) sayi1 = int(input('sayı 1:')) sayi2 = int(input('sayı 2:')) asalSayılariBul(sayi1, sayi2)

3- Kendisine gönderilen bir sayının tam bölenlerini bulan python uygulamasını yapınız.

def tamBolenleriBul(sayi):     tamBolenler = []     for i in range(2, sayi):         if (sayi % i == 0):             seafoodplus.info(i)         return tamBolenler print(tamBolenleriBul(20))

Fonksiyonlar¶

İlk derslerimizden bu yana bir şey özellikle dikkatinizi çekmiş olmalı: İlk andan itibaren hep ‘fonksiyon’ diye bir kavramdan söz ettik; üstelik yazdığımız kodlarda da bu fonksiyon denen şeyi bolca kullandık. Evet, belki bu kavramı şimdiye dek enine boyuna inceleme fırsatımız hiç olmadı, ama yine de adının fonksiyon olduğunu söylediğimiz pek çok araç tanıdık bu noktaya gelinceye kadar.

Herhalde, ‘Fonksiyon denince aklınıza ilk ne geliyor?’ diye bir soru sorsam, vereceğiniz cevap fonksiyonu olacaktır. Gerçekten de bu fonksiyonu ilk derslerimizden bu yana o kadar sık kullandık ki, fonksiyon denince aklınıza ilk bu fonksiyonun gelmesi gayet doğal.

Elbette öğrendiğimiz tek fonksiyon değildi. Bunun dışında diye bir fonksiyondan da söz etmiştik. kadar olmasa da, fonksiyonunu da yazdığımız kodlarda epey kullandık. ve dışında, fonksiyon olarak , ve benzeri araçlarla da tanıştık. Bunların dışında pek çok başka fonksiyon da Python’la birlikte hayatımıza girdi.

İşte bu bölümde, en baştan bu yana sıklıkla sözünü ettiğimiz, ama hiçbir zaman tam anlamıyla ele almadığımız bu kavramı daha iyi anlayabilmek için, fonksiyon konusunu ayrıntılı olarak ele alacağız. Bu bölümde amacımız fonksiyonları enine boyuna inceleyerek, okurun bilgi dağarcığında fonksiyonlara ilişkin sağlam bir altyapı oluşturmaktır. Okur, bu bölümü bitirdikten sonra fonksiyonlara ilişkin olarak bilmesi gereken her şeyi öğrenmiş olacak.

Fonksiyon Nedir ve Ne İşe Yarar?¶

Biz şimdiye dek karşılaştığımız , , ve gibi örnekler sayesinde ‘fonksiyon’ denen şeyi az çok tanıdığımızı söyleyebiliriz. Dolayısıyla fonksiyonun ne demek olduğunu şeklen de olsa biliyoruz ve hatta fonksiyonları kodlarımız içinde etkili bir şekilde kullanabiliyoruz.

İlk derslerimizden bu yana öğrendiğimiz fonksiyonlara şöyle bir bakacak olursak, fonksiyonların görünüşüne ve yapısına dair herhalde şu tespitleri yapabiliriz:

  1. Her fonksiyonun bir adı bulunur ve fonksiyonlar sahip oldukları bu adlarla anılır. ( fonksiyonu, fonksiyonu, fonksiyonu, fonksiyonu, fonksiyonu vb.)

  2. Şekil olarak, her fonksiyonun isminin yanında birer parantez işareti bulunur. (, , , vb.)

  3. Bu parantez işaretlerinin içine, fonksiyonlara işlevsellik kazandıran bazı parametreler yazılır. (, , vb.)

  4. Fonksiyonlar farklı sayıda parametre alabilir. Örneğin fonksiyonu toplam adet parametre alabilirken, fonksiyonu yalnızca tek bir parametre alır.

  5. Fonksiyonların isimli ve isimsiz parametreleri vardır. fonksiyonundaki sep, end ve file parametreleri isimli parametrelere örnekken, mesela kodunda Merhaba Dünya! parametresi isimsiz bir parametredir. Aynı şekilde gibi bir kodda Adınız: parametresi isimsiz bir parametredir.

  6. Fonksiyonların, isimli ve isimsiz parametreleri dışında, bir de varsayılan değerli parametreleri vardır. Örneğin fonksiyonunun sep, end ve file parametreleri varsayılan değerli parametrelere birer örnektir. Eğer bir parametrenin varsayılan bir değeri varsa, o parametreye herhangi bir değer vermeden de fonksiyonu kullanabiliriz. Python bu parametrelere, belirli değerleri öntanımlı olarak kendisi atayacaktır. Tabii eğer istersek, varsayılan değerli parametrelere kendimiz de başka birtakım değerler verebiliriz.

Fonksiyon kavramının tam olarak ne olduğunu henüz bilmiyor da olsak, şimdiye kadar öğrendiğimiz fonksiyonlara bakarak fonksiyonlar hakkında yukarıdaki çıkarımları yapabiliyoruz. Demek ki aslında fonksiyonlar hakkında alttan alta pek çok şey öğrenmişiz. O halde, fonksiyonlar hakkında şimdiden bildiklerimize güvenerek, fonksiyon kavramının ne olduğundan ziyade ne işe yaradığı konusuna rahatlıkla eğilebiliriz. Zaten fonksiyonların ne işe yaradığını öğrendikten sonra, fonksiyonların ne olduğunu da hemencecik anlayacaksınız.

Fonksiyonların ne işe yaradığını en genel ve en kaba haliyle tarif etmek istersek şöyle bir tanımlama yapabiliriz:

Fonksiyonların görevi, karmaşık işlemleri bir araya toplayarak, bu işlemleri tek adımda yapmamızı sağlamaktır. Fonksiyonlar çoğu zaman, yapmak istediğimiz işlemler için bir şablon vazifesi görür. Fonksiyonları kullanarak, bir veya birkaç adımdan oluşan işlemleri tek bir isim altında toplayabiliriz. Python’daki ‘fonksiyon’ kavramı başka programlama dillerinde ‘rutin’ veya ‘prosedür’ olarak adlandırılır. Gerçekten de fonksiyonlar rutin olarak tekrar edilen görevleri veya prosedürleri tek bir ad/çatı altında toplayan araçlardır.

Dilerseniz yukarıdaki soyut ifadeleri basit bir örnek üzerinde somutlaştırmaya çalışalım. Örneğin fonksiyonunu ele alalım.

Bu fonksiyonun görevini biliyorsunuz: fonksiyonunun görevi, kullanıcının girdiği parametreleri ekrana çıktı olarak vermektir. Her ne kadar fonksiyonunun görevini, ekrana çıktı vermek olarak tanımlasak da, aslında bu fonksiyon, ekrana çıktı vermenin yanı sıra, başka bir takım ilave işlemler de yapar. Yani bu fonksiyon, aslında aldığı parametreleri sadece ekrana çıktı olarak vermekle yetinmez. Örneğin şu komutu inceleyelim:

>>> print("Fırat","Özgül","","Adana")

Burada fonksiyonu toplam dört adet parametre alıyor. Fonksiyonumuz, görevi gereği, bu parametreleri ekrana çıktı olarak verecek. Bu komutu çalıştırdığımızda şöyle bir çıktı alıyoruz:

Dikkat ederseniz, burada salt bir ‘ekrana çıktı verme’ işleminden fazlası var. Zira fonksiyonu aldığı parametreleri şu şekilde de ekrana verebilirdi:

Veya şu şekilde:

FıratÖzgülAdana

Neticede bunlar da birer çıktı verme işlemidir. Ama dediğimiz gibi, fonksiyonu aldığı parametreleri sadece ekrana çıktı olarak vermekle yetinmiyor. Gelin isterseniz ne demek istediğimizi biraz daha açıklayalım:

fonksiyonunun yukarıdaki komutu nasıl algıladığını önceki derslerimizde öğrenmiştik. Yukarıdaki komut Python tarafından şu şekilde algılanıyor:

>>> print("Fırat","Özgül","","Adana",sep=" ",end="\n", file=seafoodplus.info,flush=False)

Yani fonksiyonu;

  1. Kendisine verilen “Fırat”, “Özgül”, “” ve “Adana” parametrelerini ekrana basıyor,

  2. sep=” “ parametresinin etkisiyle, bu parametreler arasına birer boşluk ekliyor,

  3. end=”\n” parametresinin etkisiyle, sonuncu parametreyi de ekrana bastıktan sonra bir alt satıra geçiyor,

  4. file=seafoodplus.info parametresinin etkisiyle, çıktı konumu olarak komut ekranını kullanıyor. Yani çıktıları ekrana veriyor.

  5. flush=False parametresinin etkisiyle, çıktılar ekrana gönderilmeden önce tamponda bekletiliyor.

Eğer gibi bir fonksiyon olmasaydı, yukarıda listediğimiz bütün bu işlemleri kendimiz yapmak zorunda kalacaktık. Yani ekranda göstermek istediğimiz ifadeleri ekrana çıktı olarak vermenin yanısıra, bunların ekranda nasıl görüneceğini de tek tek kendimiz elle ayarlamak zorunda kalacaktık. Ekrana çıktı verme ile ilgili pek çok işlem tek bir fonksiyonu altında birleştirildiği için, her ihtiyaç duyduğumuzda o işlemleri tek tek bizim yapmamıza gerek kalmıyor.

Aynı şey mesela fonksiyonu için de geçerlidir. Bu fonksiyonu kullanarak, programımızı kullanan kişilerle etkileşim içine girebiliyoruz. Tıpkı fonksiyonunda olduğu gibi, fonksiyonu da aslında alttan alta epey karmaşık işlemler gerçekleştirir. Ama o karmaşık işlemlerin tek bir fonksiyonu içinde bir araya getirilmiş olması sayesinde, sadece gibi basit bir komut vererek kullanıcılarımızla iletişime geçebiliyoruz.

Bu açıdan bakıldığında fonksiyonlar değişkenlere benzer. Bildiğiniz gibi, her defasında bir değeri tekrar tekrar yazmak yerine bir değişkene atayarak o değere kolayca erişebiliyoruz. Örneğin:

>>> kurum="Sosyal Sigortalar Kurumu"

Burada tanımladığımız kurum adlı değişken sayesinde, ‘Sosyal Sigortalar Kurumu’ ifadesini kullanmamız gereken her yerde sadece değişken adını kullanarak, değişkenin tuttuğu değere ulaşabiliyoruz. İşte fonksiyonlar da buna benzer bir işlev görür: Örneğin ekrana bir çıktı vermemiz gereken her yerde, yukarıda verdiğimiz karmaşık adımları tek tek gerçekleştirmeye çalışmak yerine, bu karmaşık ve rutin adımları bir araya getiren gibi bir fonksiyondan yararlanarak işlerimizi çok daha kolay bir şekilde halledebiliriz.

Bu anlattıklarımız fonksiyonların ne işe yaradığı konusunda size bir fikir vermiş olabilir. Dilerseniz bu anlattıklarımızı bir örnek aracılığıyla biraz daha somutlaştırmaya çalışalım:

Hatırlarsanız ‘Kullanıcıyla Veri Alışverişi’ başlıklı bölümde şöyle bir örnek vermiştik:

isim="Fırat"soyisim="Özgül"işsis="Ubuntu"şehir="İstanbul"print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)

Bu programı çalıştırdığımızda şöyle bir çıktı alıyoruz:

isim:Fıratsoyisim:Özgülişletimsistemi:Ubuntuşehir:İstanbul

Bu program, belli değerleri kullanarak bir kayıt oluşturma işlemi gerçekleştiriyor. Mesela yukarıdaki örnekte, ‘Fırat Özgül’ adlı şahsa ait isim, soyisim, işletim sistemi ve şehir bilgilerini alarak, bu kişi için bir kayıt oluşturuyoruz.

Peki ‘Fırat Özgül’ adlı kişinin yanısıra, ‘Mehmet Öztaban’ adlı başka bir kişi için de kayıt oluşturmak istersek ne yapacağız?

Aklınıza şöyle bir şey yazmak gelmiş olabilir:

isim1="Fırat"soyisim1="Özgül"işsis1="Ubuntu"şehir1="İstanbul"print("isim : ",isim1)print("soyisim : ",soyisim1)print("işletim sistemi: ",işsis1)print("şehir : ",şehir1)print("-"*30)isim2="Mehmet"soyisim2="Öztaban"işsis2="Debian"şehir2="Ankara"print("isim : ",isim2)print("soyisim : ",soyisim2)print("işletim sistemi: ",işsis2)print("şehir : ",şehir2)print("-"*30)

Programa her yeni kayıt eklenişinde, her yeni kişi için benzer satırları tekrar tekrar yazabilirsiniz. Peki ama bu yöntem sizce de çok sıkıcı değil mi? Üstelik bir o kadar da hataya açık bir yöntem. Muhtemelen ilk kaydı ekledikten sonra, ikinci kaydı eklerken birinci kayıttaki bilgileri kopyalayıp, bu kopya üzerinden ikinci kaydı oluşturuyorsunuz. Hatta muhtemelen kopyalayıp yapıştırdıktan sonra yeni kaydı düzenlerken bazı hatalar da yapıyor ve düzgün çalışan bir program elde edebilmek için o hataları düzeltmekle de uğraşıyorsunuz.

Bütün bu işleri kolaylaştıracak bir çözüm olsa ve bizi aynı şeyleri tekrar tekrar yazmaktan kurtarsa sizce de çok güzel olmaz mıydı? Mesela tıpkı fonksiyonu gibi, adlı bir fonksiyon olsa, biz sadece gerekli bilgileri bu fonksiyonun parantezleri içine parametre olarak yazsak ve bu fonksiyon bize istediğimiz bilgileri içeren bir kayıt oluştursa ne hoş olurdu, değil mi? Yani örneğin bahsettiğimiz bu hayali fonksiyonunu şu şekilde kullanabilseydik…

kayıt_oluştur("Mehmet","Öztaban","Debian","Ankara")

… ve bu komut bize şu çıktıyı verebilseydi…

isim:Mehmetsoyisim:Öztabanişletimsistemi:Debianşehir:Ankara

… ne kadar güzel olurdu, değil mi?

İşte böyle bir şey Python’da mümkündür. Nasıl Python geliştiricileri , ve benzeri fonksiyonları tanımlayıp, karmaşık işlemleri tek adımda yapabilmemiz için bize sunmuş ve böylece bizi her defasında tekerleği yeniden icat etme külfetinden kurtarmışsa, biz de kendi fonksiyonlarımızı tanımlayarak, kendimizi aynı işlemleri tekrar tekrar yapma zahmetinden kurtarabiliriz.

Gelin şimdi bu işi nasıl yapabileceğimizi tartışalım.

Fonksiyon Tanımlamak ve Çağırmak¶

Bir önceki bölümde, adlı hayali bir fonksiyondan söz etmiştik. Tasarımıza göre bu fonksiyon şu şekilde kullanılacak:

kayıt_oluştur("Ahmet","Gür","Pardus","İzmir")

Bu komutu verdiğimizde ise şöyle bir çıktı almayı planlıyoruz:

isim:Ahmetsoyisim:Gürişletimsistemi:Pardusşehir:İzmir

Dediğimiz gibi, böyle bir şey yapmak Python’la mümkündür. Ancak tabii ki adlı böyle bir fonksiyonu kullanabilmenin belli ön koşulları var. Nasıl sayı adlı bir değişkeni kullanabilmek için öncelikle bu ada sahip bir değişken tanımlamış olmamız gerekiyorsa, aynı şekilde adlı bir fonksiyonu kullanabilmek için de öncelikle bu ada sahip bir fonksiyonu tanımlamış olmamız gerekiyor. Zira mesela ve gibi fonksiyonları kullanabiliyor olmamız, Python geliştiricilerinin bu fonksiyonları tanımlayıp dilin içine gömmüş olmaları sayesindedir.

İşte biz de adlı fonksiyonu kullanabilmek için bu ada sahip fonksiyonu aşağıdaki şekilde tanımlamalıyız:

defkayıt_oluştur(isim,soyisim,işsis,şehir):print("-"*30)print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)print("-"*30)

İlk bakışta bu kodlar size hiçbir şey ifade etmemiş olabilir. Ama hiç endişe etmeyin. Biz birazdan bu satırların ne anlama geldiğini bütün ayrıntılarıyla anlatacağız. Siz şimdilik anlamadığınız kısımları görmezden gelip okumaya devam edin.

Yukarıdaki kodlar yardımıyla fonksiyonumuzu tanımlamış olduk. Artık elimizde, tıpkı veya gibi, adlı ‘ev yapımı’ bir fonksiyon var. Dolayısıyla bu yeni fonksiyonumuzu, daha önce öğrendiğimiz fonksiyonları nasıl kullanıyorsak aynı şekilde kullanabiliriz. Yani aşağıdaki gibi komutlar yazabiliriz:

kayıt_oluştur("Fırat","Özgül","Ubuntu","İstanbul")kayıt_oluştur("Mehmet","Öztaban","Debian","Ankara")

Yalnız fonksiyonumuzu tanımlayıp bitirdikten sonra, bu fonksiyonu kullanırken, kodlarımızın hizalamasına dikkat ediyoruz. Fonksiyonu kullanmak için yazdığımız kodları def ifadesinin hizasına getiriyoruz. Yani:

defkayıt_oluştur(isim,soyisim,işsis,şehir):print("-"*30)print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)print("-"*30)kayıt_oluştur("Fırat","Özgül","Ubuntu","İstanbul")kayıt_oluştur("Mehmet","Öztaban","Debian","Ankara")

Yukarıdaki yapıyı kullanarak, istediğiniz sayıda kayıt oluşturabilirsiniz. Mesela:

kayıt_oluştur("İlkay","Kaya","Mint","Adana")kayıt_oluştur("Seda","Kara","SuSe","Erzurum")

Gördüğünüz gibi, yukarıdaki yöntem sayesinde kodlarımızdaki tekrar eden kısımlar ortadan kalktı. Yukarıdaki fonksiyonun bize nasıl bir kolaylık sağladığını daha net görebilmek için, fonksiyon kullanarak sadece şu 11 satırla elde ettiğimiz çıktıyı, fonksiyon kullanmadan elde etmeyi deneyebilirsiniz:

defkayıt_oluştur(isim,soyisim,işsis,şehir):print("-"*30)print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)print("-"*30)kayıt_oluştur("Fırat","Özgül","Ubuntu","İstanbul")kayıt_oluştur("Mehmet","Öztaban","Debian","Ankara")kayıt_oluştur("İlkay","Kaya","Mint","Adana")kayıt_oluştur("Seda","Kara","SuSe","Erzurum")

Bu anlattıklarımız size çok karmaşık gelmiş olabilir. Ama endişe etmenize hiç gerek yok. Biraz sonra, yukarıda yazdığımız kodların hepsini didik didik edeceğiz. Ama öncelikle yukarıdaki kod parçasını yapısal olarak bir incelemenizi istiyorum. Fonksiyonu tanımladığımız aşağıdaki kod parçasına şöyle bir baktığınızda neler görüyorsunuz?

defkayıt_oluştur(isim,soyisim,işsis,şehir):print("-"*30)print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)print("-"*30)kayıt_oluştur("Fırat","Özgül","Ubuntu","İstanbul")

Bu kodları incelediğinizde şu noktalar dikkatinizi çekiyor olmalı:

  1. Kodlar def adlı bir ifade ile başlamış.

  2. Bunun ardından ‘kayıt_oluştur’ ifadesini görüyoruz.

  3. Bu ifadeyi, içinde birtakım kelimeler barındıran bir parantez çifti izliyor.

  4. Parantezin içinde, isim, soyisim, işsis ve şehir adlı değerler var.

  5. def ile başlayan bu satır iki nokta üst üste işareti ile son buluyor.

  6. İlk satırın ardından gelen kısım ilk satıra göre girintili bir şekilde yazılmış.

  7. satırı önceki satırlara göre girintisiz yazılmış.

Eğer bu kodlara dikkatlice bakacak olursanız, aslında bu kodların topu topu iki parçadan oluştuğunu göreceksiniz. İsterseniz yukarıdaki yapıyı biraz sadeleştirelim:

defkayıt_oluştur(parametre1,parametre2,parametre3,parametre4):()kayıt_oluştur(parametre1,parametre2,parametre3,parametre4)

Bu yapının ilk parçası şudur:

defkayıt_oluştur(parametre1,parametre2,parametre3,parametre4):()

İkinci parçası ise şu:

kayıt_oluştur(parametre1,parametre2,parametre3,parametre4)

Teknik olarak söylemek gerekirse, ilk parçaya ‘fonksiyon tanımı’ (function definition), ikinci parçaya ise ‘fonksiyon çağrısı’ (function call) adı verilir. Dolayısıyla bir fonksiyonun yaşam döngüsü iki aşamadan oluşur. Buna göre bir fonksiyon önce tanımlanır;

defkayıt_oluştur(parametre1,parametre2,parametre3,parametre4):()

…sonra da çağrılır;

kayıt_oluştur(parametre1,parametre2,parametre3,parametre4)

Aslında biz şimdiye kadar gördüğümüz , , vb. fonksiyonlarda bu ‘fonksiyon çağrısı’ kısmıyla zaten tanışmıştık. Zira şu komut tam anlamıyla bir fonksiyon çağrısıdır (yani bir fonksiyon çağırma işlemidir):

print("Fırat","Özgül","Adana",32)

Gördüğünüz gibi, yukarıdaki komutun yapı olarak şu komuttan hiçbir farkı yok:

kayıt_oluştur("Fırat","Özgül","Ubuntu","İstanbul")

Bu iki fonksiyon arasındaki tek fark, fonksiyonunu Python geliştiricilerinin; fonksiyonunu ise sizin tanımlamış olmanızdır.

Elbette bu iki fonksiyon yapı olarak birbirinin aynı olsa da, işlev olarak birbirinden farklıdır. fonksiyonunun görevi kendisine parametre olarak verilen değerleri ekrana çıktı vermek iken, fonksiyonunun görevi kendisine parametre olarak verilen değerleri kullanarak bir kayıt oluşturmaktır.

Bu derse gelinceye kadar öğrendiğimiz , ve gibi fonksiyonlara teknik olarak ‘gömülü fonksiyonlar’ (builtin functions) adı verilir. Bu fonksiyonlara bu adın verilmiş olmasının sebebi, bu fonksiyonların gerçekten de Python programlama dili içine gömülü bir vaziyette olmalarıdır. Dikkat ederseniz kendi yazdığımız fonksiyonları kullanabilmek için öncelikle fonksiyonu tanımlamamız gerekiyor. Gömülü fonksiyonlar ise Python geliştiricileri tarafından halihazırda tanımlanmış olduğu için bunları biz herhangi bir tanımlama işlemi yapmaya gerek kalmadan doğrudan çağırabiliyoruz.

Böylece bir fonksiyonun yapı olarak neye benzediğini üstünkörü de olsa incelemiş olduk. Buraya kadar anlatılan kısımda bazı noktaları anlamakta zorlanmış olabilirsiniz. Eğer öyleyse hiç endişelenmeyin. Bu gayet doğal.

Gelin isterseniz şimdi yukarıda anlattıklarımızın içini doldurmaya çalışalım.

Fonksiyonların Yapısı¶

İsterseniz biraz da fonksiyonların yapısından söz edelim. Böylelikle ne ile karşı karşıya olduğumuzu anlamak zihninizde biraz daha kolaylaşır.

Dedik ki, bir fonksiyonun ilk parçasına ‘fonksiyon tanımı’ (function definition) adı verilir. Bir fonksiyonu tanımlamak için def adlı bir parçacıktan yararlanıyoruz. Örneğin:

defbir_fonksiyon():()

Burada def parçacığı, tanımladığımız şeyin bir fonksiyon olduğunu gösteriyor. bir_fonksiyon ifadesi ise tanımladığımız bu fonksiyonun adıdır. Fonksiyonu tanımladıktan sonra, çağırırken bu adı kullanacağız.

ifadesinin sonundaki iki nokta işaretinden de tahmin edebileceğiniz gibi, sonraki satıra yazacağımız kodlar girintili olacak. Yani mesela:

defselamla():print("Elveda Zalim Dünya!")

Yukarıda adlı bir fonksiyon tanımlamış olduk. Bu fonksiyonun görevi ekrana Elveda Zalim Dünya! çıktısı vermektir.

Bu noktada şöyle bir soru akla geliyor: Acaba fonksiyon gövdesindeki kısım için ne kadarlık bir girinti oluşturacağız?

Girintilemeye ilişkin olarak önceki derslerde bahsettiğimiz bütün kurallar burada da geçerlidir. Fonksiyon gövdesine, def ifadesinden itibaren 4 (dört) boşlukluk bir girinti veriyoruz. def ifadesinden itibaren girintili olarak yazdığımız kısmın tamamı o fonksiyonun gövdesini oluşturur ve bütünüyle o fonksiyona aittir.

Bu kodlarla yaptığımız şey bir fonksiyon tanımlama işlemidir. Eğer bu kodları bir dosyaya kaydedip çalıştırırsak herhangi bir çıktı almayız. Çünkü henüz fonksiyonumuzu çağırmadık. Bu durumu , ve benzeri gömülü fonksiyonlara benzetebilirsiniz. Tıpkı yukarıda bizim yaptığımız gibi, gömülü fonksiyonlar da Python geliştiricileri tarafından bir yerlerde tanımlanmış vaziyette dururlar, ama biz bu fonksiyonları yazdığımız programlarda çağırana kadar bu fonksiyonlar çalışmaz.

Daha önce de dediğimiz gibi, bir fonksiyonun yaşam döngüsü iki aşamadan oluşur: Fonksiyon tanımı ve fonksiyon çağrısı. Yukarıda bu döngünün sadece fonksiyon tanımı aşaması mevcut. Unutmayın, bir fonksiyon çağrılmadan asla çalışmaz. Bir fonksiyonun çalışabilmesi için o fonksiyonun tanımlandıktan sonra çağrılması gerekir. Örneğin fonksiyonu Python’ın derinliklerinde bir yerlerde tanımlanmış vaziyette durur. Bu fonksiyon, biz onu çağırana kadar, bulunduğu yerde sessizce bekler. Aynı şekilde adlı fonksiyon da programımız içinde tanımlanmış vaziyette, bizim onu çağıracağımız anı bekliyor. Bu söylediklerimizi destekleyecek açıklayıcı bilgileri biraz sonra vereceğiz. Biz şimdilik fonksiyon tanımı kısmını incelemeye devam edelim.

Bu arada yukarıdaki fonksiyon tanımının yapısına çok dikkat edin. İki nokta üst üste işaretinden sonraki satırda girintili olarak yazılan bütün kodlar (yani fonksiyonun gövde kısmı) fonksiyonun bir parçasıdır. Girintinin dışına çıkıldığı anda fonksiyon tanımlama işlemi de sona erer.

Örneğin:

defselamla():print("Elveda Zalim Dünya!")selamla()

İşte burada fonksiyonumuzu çağırmış olduk. Dikkat edin! Dediğim gibi, iki nokta üst üste işaretinden sonraki satırda girintili olarak yazılan bütün kodlar fonksiyona aittir. satırı ise fonksiyon tanımının dışında yer alır. Bu satırla birlikte girintinin dışına çıkıldığı için artık fonksiyon tanımlama safhası sona ermiş oldu.

Biz yukarıdaki örnekte, adlı fonksiyonu tanımlar tanımlamaz çağırmayı tercih ettik. Ama elbette siz bir fonksiyonu tanımlar tanımlamaz çağırmak zorunda değilsiniz. Yazdığınız bir program içinde fonksiyonlarınızı tanımladıktan sonra, ihtiyacınıza bağlı olarak, programın herhangi başka bir yerinde fonksiyonlarınızı çağırabilirsiniz.

Fonksiyonlarla ilgili söylediklerimizi toparlayacak olursak şöyle bir bilgi listesi ortaya çıkarabiliriz:

  1. Python’da kabaca iki tip fonksiyon bulunur. Bunlardan biri gömülü fonksiyonlar (builtin functions), öteki ise özel fonksiyonlardır (custom functions). Burada ‘özel’ ifadesi, ‘kullanıcının ihtiyaçlarına göre kullanıcı tarafından özel olarak üretilmiş’ anlamına gelir.

  2. Gömülü fonksiyonlar; Python geliştiricileri tarafından tanımlanıp dilin içine gömülmüş olan , , , , vb. fonksiyonlardır. Bu fonksiyonlar halihazırda tanımlanıp hizmetimize sunulduğu için bunları biz herhangi bir tanımlama işlemi yapmadan doğrudan kullanabiliriz.

  3. Özel fonksiyonlar ise, gömülü fonksiyonların aksine, Python geliştiricileri tarafından değil, bizim tarafımızdan tanımlanmıştır. Bu fonksiyonlar dilin bir parçası olmadığından, bu fonksiyonları kullanabilmek için bunları öncelikle tanımlamamız gerekir.

  4. Python’da bir fonksiyonun yaşam döngüsü iki aşamadan oluşur: Tanımlanma ve çağrılma.

  5. Bir fonksiyonun çağrılabilmesi (yani kullanılabilmesi) için mutlaka birisi tarafından tanımlanmış olması gerekir.

  6. Fonksiyonu tanımlayan kişi Python geliştiricileri olabileceği gibi, siz de olabilirsiniz. Ama neticede ortada bir fonksiyon varsa, bir yerlerde o fonksiyonun tanımı da vardır.

  7. Fonksiyon tanımlamak için def adlı bir ifadeden yararlanıyoruz. Bu ifadeden sonra, tanımlayacağımız fonksiyonun adını belirleyip iki nokta üst üste işareti koyuyoruz. İki nokta üst üste işaretinden sonra gelen satırlar girintili olarak yazılıyor. Daha önce öğrendiğimiz bütün girintileme kuralları burada da geçerlidir.

  8. Fonksiyonun adını belirleyip iki nokta üst üste koyduktan sonra, alt satırda girintili olarak yazdığımız bütün kodlar fonksiyonun gövdesini oluşturur. Doğal olarak, bir fonksiyonun gövdesindeki bütün kodlar o fonksiyona aittir. Girintinin dışına çıkıldığı anda fonksiyon tanımı da sona erer.

Fonksiyonlarla ilgili öğrendiklerimizi toparladığımıza göre, gelin isterseniz fonksiyonlarla ilgili bir örnek yaparak, bu yapıyı daha iyi anlamaya çalışalım:

defsistem_bilgisi_göster():importsysprint("\nSistemde kurulu Python'ın;")print("\tana sürüm numarası:",seafoodplus.infon_seafoodplus.info)print("\talt sürüm numarası:",seafoodplus.infon_seafoodplus.info)print("\tminik sürüm numarası:",seafoodplus.infon_seafoodplus.info)print("\nKullanılan işletim sisteminin;")print("\tadı:",seafoodplus.inform)

Burada adlı bir fonksiyon tanımladık. Bu fonksiyonun görevi, kullanıcının sistemindeki Python sürümü ve işletim sistemine dair birtakım bilgiler vermektir.

Bu arada, bu kodlarda, daha önceki derslerimizde öğrendiğimiz sys modülünden ve bu modül içindeki değişkenlerden yararlandığımızı görüyorsunuz. Bu kodlarda sys modülünün içindeki şu araçları kullandık:

  1. version_seafoodplus.info: Python’ın ana sürüm numarası (Örn. 3)

  2. version_seafoodplus.info: Python’ın alt sürüm numarası (Örn. 4)

  3. version_seafoodplus.info: Python’ın minik sürüm numarası (Örn. 0)

  4. platform: Kullanılan işletim sisteminin adı (Örn. ‘win32’ veya ‘linux2’)

Yukarıda tanımladığımız fonksiyonu nasıl çağıracağımızı biliyorsunuz:

Bu fonksiyonun tanımını ve çağrısını eksiksiz bir program içinde gösterelim:

defsistem_bilgisi_göster():importsysprint("\nSistemde kurulu Python'ın;")print("\tana sürüm numarası:",seafoodplus.infon_seafoodplus.info)print("\talt sürüm numarası:",seafoodplus.infon_seafoodplus.info)print("\tminik sürüm numarası:",seafoodplus.infon_seafoodplus.info)print("\nKullanılan işletim sisteminin;")print("\tadı:",seafoodplus.inform)sistem_bilgisi_göster()

Bu kodları bir dosyaya kaydedip çalıştırdığımızda şuna benzer bir çıktı alacağız:

SistemdekuruluPython'ın;anasürümnumarası:3altsürümnumarası:3miniksürümnumarası:0Kullanılanişletimsisteminin;adı:linux

Demek ki bu kodların çalıştırıldığı sistem Python’ın sürümünün kurulu olduğu bir GNU/Linux işletim sistemi imiş…

Fonksiyonlar Ne İşe Yarar?¶

Şimdiye kadar söylediklerimizden ve verdiğimiz örneklerden fonksiyonların ne işe yaradığını anlamış olmalısınız. Ama biz yine de fonksiyonların faydası üzerine birkaç söz daha söyleyelim. Böylece fonksiyonların ne işe yaradığı konusunda aklımızda hiçbir şüphe kalmaz…

İsterseniz bir örnek üzerinden ilerleyelim.

Diyelim ki, bir sayının karesini bulan bir program yazmak istiyoruz. Şimdiye kadarki bilgilerimizi kullanarak şöyle bir şey yazabiliriz:

sayı=12çıktı="{} sayısının karesi {} sayısıdır"print(çıktı.format(sayı,sayı**2))

Yukarıdaki programı çalıştırdığımızda şöyle bir çıktı elde edeceğiz:

12sayısınınkaresisayısıdır

Gayet güzel. Şimdi şöyle bir durum hayal edin: Diyelim ki büyük bir program içinde, farklı farklı yerlerde yukarıdaki işlemi tekrar tekrar yapmak istiyorsunuz. Böyle bir durumda şöyle bir şey yazmanız gerekebilir:

sayı=12çıktı="{} sayısının karesi {} sayısıdır"print(çıktı.format(sayı,sayı**2))####programla ilgili başka kodlar###sayı=15print(çıktı.format(sayı,sayı**2))###programla ilgili başka kodlar###sayı=29print(çıktı.format(sayı,sayı**2))

Buradaki sorun, aynı şeyleri tekrar tekrar yazmak zorunda kalmamızdır. Bu küçük örnekte pek belli olmuyor olabilir, ama özellikle büyük programlarda aynı kodların program içinde sürekli olarak tekrarlanması pek çok probleme yol açar. Örneğin kodlarda bir değişiklik yapmak istediğinizde, tekrarlanan kısımları bulup hepsinin üzerinde tek tek değişiklik yapmanız gerekir. Mesela çıktı adlı değişkenin içeriğini değiştirmek isterseniz, yaptığınız değişiklik programınızın pek çok kısmını etkileyebilir. Örneğin, çıktı değişkenini şu şekle getirdiğinizi düşünün:

çıktı="{} sayısının karesi {}, karekökü {} sayısıdır"

Böyle bir durumda, program içinde geçen bütün satırlarını bulup, üçüncü {} işaretine ait işlemi parantez içine eklemeniz gerekir. Tahmin edebileceğiniz gibi, son derece sıkıcı, yorucu ve üstelik hata yapmaya açık bir işlemdir bu. İşte bu tür problemlere karşı fonksiyonlar çok iyi bir çözümdür.

Yukarıda bahsettiğimiz kare bulma işlemi için şu şekilde basit bir fonksiyon tanımlayabiliriz:

defkare_bul():sayı=12çıktı="{} sayısının karesi {} sayısıdır"print(çıktı.format(sayı,sayı**2))

Bu fonksiyonu tanımladık. Şimdi de fonksiyonumuzu çağıralım:

Kodlarımız tam olarak şöyle görünüyor:

defkare_bul():sayı=12çıktı="{} sayısının karesi {} sayısıdır"print(çıktı.format(sayı,sayı**2))kare_bul()

Burada fonksiyonumuz satırıyla başlıyor, satırıyla bitiyor. Daha sonra gelen kodu, girintinin dışında yer aldığı için fonksiyon tanımına ait değildir.

Bu kodları bir dosyaya kaydedip çalıştırdığımızda alacağımız çıktı şu olacaktır:

12sayısınınkaresisayısıdır

adlı fonksiyonu bir kez tanımladıktan sonra bu fonksiyonu programınız içinde gereken her yerde çağırabilirsiniz:

kare_bul()####programla ilgili başka kodlar###kare_bul()###programla ilgili başka kodlar###kare_bul()

Gördüğünüz gibi adlı bu fonksiyon bizi pek çok zahmetten kurtarıyor. Ancak bu fonksiyonun bir sorunu var. Bu fonksiyon ekrana yalnızca 12 sayısının karesi sayısıdır çıktısı verebiliyor. Buradaki problem, fonksiyonun sadece 12 sayısı üzerinde işlem yapabilmesi. Şöyle bir düşününce, bu çıktının ne kadar anlamsız olduğunu, aslında yukarıdaki fonksiyonun tamamen gereksiz bir iş yaptığını rahatlıkla görebiliyoruz. Fonksiyonumuzun adı . Ama dediğimiz gibi, fonksiyonumuz sadece 12 sayısının karesini söyleyebiliyor. Halbuki mantık olarak fonksiyonumuzun, bütün sayıların karesini söyleyebilmesini beklerdik.

Not

Bu arada, gördüğünüz gibi, yukarıdaki fonksiyon parametresiz bir fonksiyondur. Dolayısıyla bu fonksiyonu çağırırken parantez içinde herhangi bir değer belirtmiyoruz.

Fonksiyonumuzun gerçek anlamda işlevli bir hale gelebilmesi için sadece tek bir sayıyı değil, bütün sayıları inceleyebiliyor olması gerek. İşte fonksiyonumuza bu yeteneği parametreler aracılığıyla kazandırabiliriz.

Dikkatlice bakın:

defkare_bul(sayı):çıktı="{} sayısının karesi {} sayısıdır"print(çıktı.format(sayı,sayı**2))

Fonksiyona parametre olarak nasıl bir isim verdiğinizin önemi yoktur. Parantez içine parametre olarak istediğiniz kelimeyi yazabilirsiniz. Önemli olan, parantez içinde fonksiyonun kaç parametre alacağını gösteren bir işaret olmasıdır. Mesela yukarıdaki fonksiyonu şöyle de tanımlayabilirdik:

defkare_bul(i):çıktı="{} sayısının karesi {} sayısıdır"print(çıktı.format(i,i**2))

…veya şöyle:

defkare_bul(osman):çıktı="{} sayısının karesi {} sayısıdır"print(çıktı.format(osman,osman**2))

Elbette parametre adı olarak akılda kalıcı ve daha mantıklı bir seçim yapmak işlerinizi kolaylaştıracaktır…

Şimdi de yukarıdaki fonksiyonu çağıralım:

Bu fonksiyonu çalıştırdığımızda şu çıktıyı alırız:

9sayısınınkaresi81sayısıdır

Bu fonksiyona parametre olarak hangi sayıyı verirseniz o sayının karesi hesaplanacaktır. Örneğin:

kare_bul(15)kare_bul()

Yine bu fonksiyonu programınız içinde gereken her yerde çağırabilirsiniz:

kare_bul(17)####programla ilgili başka kodlar###kare_bul(21)###programla ilgili başka kodlar###kare_bul()

Fonksiyonu oluşturan kodlarda herhangi bir değişiklik yapmak istediğinizde sadece fonksiyon tanımının gövdesini değiştirmeniz yeterli olacaktır. Örneğin:

defkare_bul(sayı):çıktı="{} sayısının karesi {}, karekökü ise {} sayısıdır"print(çıktı.format(sayı,sayı**2,sayı**))

Bu sayede sadece fonksiyon gövdesinde değişiklik yaparak, programın başka kısımlarını hiç etkilemeden yolumuza devam edebiliyoruz.

Buraya kadar anlattıklarımız, fonksiyonların ne işe yaradığı ve bir program yazarken neden fonksiyonlara ihtiyaç duyacağımız konusunda size bir fikir vermiş olmalı. Eğer hala aklınızda fonksiyonların faydası konusunda bir şüphe kaldıysa, fonksiyonların faydasını anlamanızı sağlayabilmek için size şöyle bir soru sormama izin verin: Acaba ‘istihza’ kelimesinin kaç karakterden oluştuğunu nasıl buluruz?

‘Elbette fonksiyonunu kullanarak!’ dediğinizi duyar gibiyim. Gerçekten de Python’da bir karakter dizisinin uzunluğunu bulmanın en iyi yolu fonksiyonunu kullanmaktır:

>>> len("istihza")7

Peki ya Python’da diye bir fonksiyon olmasaydı ne yapacaktınız? Böyle bir durumda, karakter dizilerinin uzunluğunu ölçmek için sizin bir yöntem icat etmeniz gerekecekti. Mesela ‘istihza’ kelimesinin kaç karakterden oluştuğunu bulmak için şöyle bir kod yazacaktınız:

c=0forsin"istihza":c+=1print(c)

Burada önce c adlı bir değişken tanımlayıp, bu değişkenin değerini 0 yaptık. Bu değişken, uzunluğunu sorgulamak istediğimiz kelimenin kaç karakterden oluştuğu bilgisini saklayacak.

Ardından bir döngüsü tanımlıyoruz. Bu döngüde, ‘istihza’ kelimesindeki her bir karakter için c değişkeninin değerini 1 sayı artırıyoruz. Böylece döngü sonunda c değişkeni ‘istihza’ kelimesi içinde kaç karakter olduğu bilgisini tutmuş oluyor.

Son olarak da c değişkeninin nihai değerini ekrana yazdırıyoruz.

Bu kodları çalıştırdığınızda 7 cevabı alacaksınız. Demek ki ‘istihza’ kelimesinde 7 karakter varmış. Peki ‘istihza’ kelimesi yerine mesela ‘Afyonkarahisar’ kelimesi içinde kaç karakter olduğunu hesaplamak isterseniz ne yapacaksınız? Elbette yukarıdaki kodları tekrar yazıp, ‘istihza’ kelimesini ‘Afyonkarahisar’ kelimesi ile değiştireceksiniz. Böylece bu kelimenin kaç karakterden oluştuğunu bulmuş olacaksınız. Sorgulamak istediğiniz her kelime için aynı şeyleri yapabilirsiniz…

Ne kadar verimsiz bir yöntem, değil mi?

Halbuki hiç bu tür şeylerle uğraşmaya gerek yok. Eğer Python bize fonksiyonu gibi bir fonksiyon vermemiş olsaydı, kendi fonksiyonumuzu icat edebilirdik. Dikkatlice bakın:

defuzunluk(öğe):c=0forsinöğe:c+=1print(c)

Böylece adı uzunluk olan bir fonksiyon tanımlamış olduk. Artık bir öğenin uzunluğunu hesaplamak istediğimizde, bütün o kodları her defasında tekrar tekrar yazmak yerine sadece fonksiyonunu kullanabiliriz:

uzunluk("istihza")uzunluk("Afyonkarahisar")uzunluk("Tarım ve Köyişleri Bakanlığı")

Üstelik bu fonksiyon yalnızca karakter dizilerinin değil öteki veri tiplerinin de uzunluğunu hesaplayabilir:

liste=["ahmet","mehmet","veli"]uzunluk(liste)

Verdiğimiz bu örnek bize hem gömülü fonksiyonların faydasını, hem de genel olarak fonksiyonların ne işe yaradığını açıkça gösteriyor. Buna göre, benzeri gömülü fonksiyonlar tekerleği yeniden icat etme derdinden kurtarıyor bizi. Örneğin Python geliştiricilerinin gibi bir fonksiyon tanımlamış olmaları sayesinde, bir karakter dizisinin uzunluğunu hesaplamak için kendi kendimize yöntem icat etmek zorunda kalmıyoruz. Ama eğer kendi yöntemimizi icat etmemiz gerekirse, istediğimiz işlevi yerine getiren bir fonksiyon tanımlamamız da mümkün.

Böylece temel olarak fonksiyonların ne işe yaradığını, neye benzediğini, nasıl tanımlandığını ve nasıl çağrıldığını incelemiş olduk. Şimdi fonksiyonların biraz daha derinine dalmaya başlayabiliriz.

Parametreler ve Argümanlar¶

Şimdiye kadar yaptığımız örnekler sayesinde aslında parametrelerin neye benzediğini ve ne işe yaradığını öğrenmiştik. Bu bölümde ise sizi ‘argüman’ adlı bir kavramla tanıştırıp, argüman ile parametre arasındaki benzerlik ve farklılıkları inceleyeceğiz. Bunun yanısıra, parametre kavramını da bu bölümde daha derinlikli bir şekilde ele alacağız.

O halde hemen yola koyulalım.

Parametrenin ne olduğunu biliyorsunuz. Bunlar fonksiyon tanımlarken parantez içinde belirttiğimiz, fonksiyon gövdesinde yapılan işin değişken öğelerini gösteren parçalardır. Mesela:

defkopyala(kaynak_dosya,hedef_dizin):çıktı="{} adlı dosya {} adlı dizin içine kopyalandı!"print(çıktı.format(kaynak_dosya,hedef_dizin))

Burada adlı bir fonksiyon tanımladık. Bu fonksiyon toplam iki adet parametre alıyor: kaynak_dosya ve hedef_dizin. Gördüğünüz gibi, bu iki parametre gerçekten de fonksiyon gövdesinde yapılan işin değişken öğelerini gösteriyor. Bu fonksiyonun üreteceği çıktı, fonksiyonu çağıran kişinin bu iki parametreye vereceği değerlere bağlı olarak şekillenecek.

Bildiğiniz gibi, parametrelere ne ad verdiğinizin hiçbir önemi yok. Elbette parametrenin görevine uygun bir isim vermeniz fonksiyonunuzun okunaklılığını artıracaktır. Ama tabii ki bu fonksiyonu pekala şu parametrelerle de tanımlayabilirdik:

defkopyala(a,b):çıktı="{} adlı dosya {} adlı dizin içine kopyalandı!"print(çıktı.format(a,b))

Burada önemli olan, parametre görevi görecek iki adet kelime bulmak. Bu kelimelerin ne olduğunun önemi yok. Ama tabii ki kaynak_dosya ve hedef_dizin adları, a ve b adlarına kıyasla, fonksiyondaki parametrelerin yaptığı işi çok daha iyi tarif ediyor.

Parametre adı belirleme kuralları değişken adı belirleme kurallarıyla aynıdır. Dolayısıyla bir değişken adı belirlerken neye dikkat ediyorsak, parametre adı belirlerken de aynı şeye dikkat etmeliyiz.

Gelin şimdi isterseniz tanımladığınız bu fonksiyonu çağıralım:

kopyala("seafoodplus.info","/home/istihza/Desktop")

Kodlarımız dosya içinde tam olarak şöyle görünüyor:

defkopyala(kaynak_dosya,hedef_dizin):çıktı="{} adlı dosya {} adlı dizin içine kopyalandı!"print(çıktı.format(kaynak_dosya,hedef_dizin))kopyala("seafoodplus.info","/home/istihza/Desktop")

Bu kodları bir dosyaya kaydedip çalıştırdığımızda şöyle bir çıktı alırız:

seafoodplus.info adlı dosya /home/istihza/Desktop adlı dizin içine kopyalandı!

Gördüğünüz gibi, “seafoodplus.info” ve “/home/istihza/Desktop” değerleri, çıktı adlı karakter dizisinde uygun yerlere yerleştirildi ve ekrana çıktı olarak verildi. İşte burada gördüğünüz bu “seafoodplus.info” ve “/home/istihza/Desktop” değerlerine argüman adı verilir. Yani bir fonksiyonu tanımlarken belirlediğimiz adlara parametre, aynı fonksiyonu çağırırken belirlediğimiz adlara ise argüman deniyor. Dolayısıyla fonksiyon tanımında belirlediğimiz kaynak_dosya ve hedef_dizin adlı değişkenler birer parametre, fonksiyon çağrısında bu parametrelere karşılık gelen “seafoodplus.info” ve “/home/istihza/Desktop” değerleri ise birer argüman oluyor.

Böylece parametre ve argüman arasındaki farkı öğrenmiş olduk. Ancak şunu belirtmekte yarar var: Bu iki kavram genellikle birbirinin yerine kullanılır. Yani bu iki kavram arasındaki, yukarıda açıkladığımız farka pek kimse dikkat etmez. Dolayısıyla pek çok yerde hem parametre hem de argüman için aynı ifadenin kullanıldığını görebilirsiniz. Özellikle Türkçede parametre kelimesi argüman kelimesine kıyasla daha bilinir ve yaygın olduğu için, ayrım yapılmaksızın hem fonksiyon çağrısındaki değerlere, hem de fonksiyon tanımındaki değerlere parametre adı verilir.

Gelelim parametrelerin çeşitlerine…

Python’da parametreler işlevlerine göre farklı kategorilere ayrılır. Gelin şimdi bu kategorileri tek tek inceleyelim.

Sıralı (veya İsimsiz) Parametreler¶

Python’da şöyle bir fonksiyon tanımlayabileceğimizi biliyoruz:

defkayıt_oluştur(isim,soyisim,işsis,şehir):print("-"*30)print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)print("-"*30)

Yukarıda tanımladığımız bu fonksiyonu şu şekilde çağırabiliriz:

kayıt_oluştur("Ahmet","Öz","Debian","Ankara")

Bu fonksiyonda, yazdığımız parametrelerin sırası büyük önem taşır. Mesela yukarıdaki fonksiyonu şöyle çağırdığımızı düşünün:

kayıt_oluştur("Debian","Ankara","Öz","Ahmet")

Eğer fonksiyon parametrelerini bu sırayla kullanırsak aldığımız çıktı hatalı olacaktır:

isim:Debiansoyisim:Ankaraişletimsistemi:Özşehir:Ahmet

Gördüğünüz gibi, isim, soyisim ve öteki bilgiler birbirine karışmış. İşte Python’da, veriliş sırası önem taşıyan bu tür parametrelere ‘sıralı parametreler’ (veya isimsiz parametreler) adı verilir.

İsimli Parametreler¶

Bir önceki bölümde verdiğimiz şu örneği yeniden ele alalım:

defkayıt_oluştur(isim,soyisim,işsis,şehir):print("-"*30)print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)print("-"*30)

Bu fonksiyonu çağırırken parametrelerin sırasını doğru vermenin, alacağımız çıktının düzgün olması bakımından büyük önem taşıdığını biliyoruz. Ancak özellikle parametre sayısının çok olduğu fonksiyonlarda parametre sırasını akılda tutmak zor olabilir. Böyle durumlarda parametreleri isimleri ile birlikte kullanmayı tercih edebiliriz:

kayıt_oluştur(soyisim="Öz",isim="Ahmet",işsis="Debian",şehir="Ankara")

Böylece fonksiyon parametrelerini istediğimiz sıra ile kullanabiliriz. Ancak burada dikkat etmemiz gereken bazı noktalar var. Python’da isimli bir parametrenin ardından sıralı bir parametre gelemez. Yani şu kullanım yanlıştır:

kayıt_oluştur(soyisim="Öz",isim="Ahmet","Debian","Ankara")

Bu kodlar bize şu hatayı verir:

File"<stdin>",line1SyntaxError:non-keywordargafterkeywordarg

Bu yüzden, eğer isimli parametreler kullanacaksak, isimli parametrelerden sonra sıralı parametre kullanmamaya dikkat ediyoruz.

Varsayılan Değerli Parametreler¶

Şimdiye kadar karşılaştığımız fonksiyonlarda bir şey dikkatinizi çekmiş olmalı. Mesela fonksiyonunu ele alalım. Bildiğiniz gibi, bu fonksiyonu en basit şekilde şöyle kullanıyoruz:

print("Fırat","Özgül")

Evet, fonksiyonunu bu şekilde kullanabiliyoruz, ancak bildiğiniz gibi, aslında bu fonksiyonun bazı özel parametreleri de var. Daha önceki derslerimizden hatırlayacağınız gibi, biz yukarıdaki komutu verdiğimizde aslında Python bunu şu şekilde algılıyor:

print("Fırat","Özgül",sep=" ",end="\n",file=seafoodplus.info,flush=False)

Yani biz görmesek de aslında her çağrısı sep, end, file ve flush parametrelerini de içeriyor. Biz bu özel parametreleri kullanmasak da, yazdığımız kod düzgün bir şekilde çalışır. Bunun nedeni, sep, end, file ve flush parametrelerinin öntanımlı olarak birtakım değerlere sahip olmasıdır. Yani biz bu parametrelere kendimiz bir değer atamazsak Python bu parametrelere kendi belirlediği bazı öntanımlı değerleri atayacaktır. Dolayısıyla, eğer biz başka bir değer yazmazsak, sep parametresi ” “ değerine, end parametresi “n” değerine, file parametresi seafoodplus.info değerine, flush parametresi ise False değerine sahip olacaktır. İşte bu tür parametrelere Python’da ‘varsayılan değerli parametreler’ adı verilir. Peki biz kendimiz varsayılan değerli parametreler içeren fonksiyonları nasıl tanımlayabiliriz?

Şu örneğe dikkatlice bakın:

defkur(kurulum_dizini="/usr/bin/"):print("Program {} dizinine kuruldu!".format(kurulum_dizini))

Burada adlı bir fonksiyon tanımladık. Bu fonksiyonun görevi, yazdığımız bir programı, kullanıcının bilgisayarındaki bir dizine kurmak ve programın hangi dizine kurulduğu konusunda kullanıcıyı bilgilendirmek. Bu fonksiyonu şu şekilde çağırabiliriz:

Eğer fonksiyonunu böyle çağırırsak bize şu çıktıyı verecektir:

Program /usr/bin/ dizinine kuruldu!

Gördüğünüz gibi, fonksiyonunun kurulum_dizini adlı bir parametresi var. Biz fonksiyonu tanımlarken, bu parametreye bir varsayılan değer atadık (/usr/bin/). Böylece fonksiyonu parametresiz olarak çağrıldığında bu varsayılan değer devreye girdi. Eğer biz bu değeri değiştirmek istersek, mesela programımızın “C:\Users\firat” dizinine kurulmasını istersek, fonksiyonunu şöyle çağırmalıyız:

kur("C:\\Users\\firat")

fonksiyonunu yukarıdaki gibi çağırdığımızda Python bize şöyle bir çıktı verir:

Program C:\Users\firat dizinine kuruldu!

Bu örnek size, varsayılan değerli parametreler belirlemenin ne kadar faydalı olabileceğini göstermiş olmalı. Mesela bir program yazdığınızı düşünün. Programınızı indiren kullanıcılar, yukarıdaki gibi bir varsayılan değerli parametre belirlemiş olmanız sayesinde programınızı nereye kuracaklarını belirlemek zorunda kalmadan bir sonraki kurulum adımına geçebiliyorlar…

Elbette eğer isterseniz kullanıcılarınızı bir kurulum dizini belirlemeye zorlamak da isteyebilirsiniz. Bunun için yine varsayılan değerli parametrelerden yararlanabilirsiniz:

defkur(kurulum_dizini=''):ifnotkurulum_dizini:print("Lütfen programı hangi dizine kurmak istediğinizi belirtin!")else:print("Program {} dizinine kuruldu!".format(kurulum_dizini))

Bu defa kurulum_dizini parametresinin varsayılan değerini boş bir karakter dizisi olarak belirledik. Eğer bu parametrenin değeri boş bir karakter dizisi olursa, kullanıcı herhangi bir kurulum dizini belirtmemiş demektir. Eğer kullanıcı herhangi bir kurulum dizini belirtmezse kurulum_dizini parametresinin bool değeri False olacaktır. Bu özelliği dikkate alarak fonksiyon gövdesinde şu kodları kullanabiliyoruz:

ifnotkurulum_dizini:print("Lütfen programı hangi dizine kurmak istediğinizi belirtin!")

Böylece, kurulum_dizini parametresinin bool değeri False olursa kullanıcılarımıza şöyle bir uyarı gösteriyoruz:

"Lütfen programı hangi dizine kurmak istediğinizi belirtin!"

Dolayısıyla kuruluma başlayabilmek için fonksiyonunun şöyle çalıştırılmasını zorunlu tutuyoruz:

kur("C:\\Users\\istihza")

Buna benzer durumlarla pek çok kez karşılaşmış olmalısınız. Özellikle programların kurulmasını sağlayan ‘setup’ betiklerinde her aşama için bir varsayılan değer belirlenip, kullanıcının sadece ‘Next’ tuşlarına basarak sağlıklı bir kurulum yapması sağlanabiliyor. Eğer kullanıcı varsayılan değerlerin dışında birtakım değerler belirlemek isterse, yukarıda örneğini verdiğimiz yapı kullanıcıya böyle bir özgürlük de sağlıyor.

Rastgele Sayıda İsimsiz Parametre Belirleme¶

Şimdiye kadar öğrendiğimiz pek çok fonksiyonun toplam kaç parametre alabileceği bellidir. Örneğin fonksiyonu yalnızca tek bir parametre alabilir. Eğer bu fonksiyona birden fazla parametre verirsek Python bize bir hata mesajı gösterecektir. Aynı şekilde mesela fonksiyonunun da kaç parametre alabileceği bellidir. Ama örneğin fonksiyonuna verebileceğimiz parametre sayısı (teknik olarak ile sınırlı olsa da) pratik olarak neredeyse sınırsızdır.

Peki acaba biz kendimiz, sınırsız parametre alabilen fonksiyonlar üretebilir miyiz?

Bu sorunun cevabı ‘evet’ olacaktır. Şimdi şu örneğe dikkatlice bakın:

deffonksiyon(*parametreler):print(parametreler)fonksiyon(1,2,3,4,5)

Bu kodları çalıştırdığımızda şu çıktıyı alacağız:

Gördüğünüz gibi, fonksiyon tanımı içinde kullandığımız * işareti sayesinde fonksiyonumuzun pratik olarak sınırsız sayıda parametre kabul etmesini sağlayabiliyoruz. Bu arada, bu tür fonksiyonların alabileceği parametre sayısı, dediğimiz gibi, pratikte sınırsızdır, ama teknik olarak bu sayı adedi geçemez.

Yukarıdaki kodların verdiği çıktının bir demet olduğuna dikkatinizi çekmek isterim. Bu bilgiye sahip olduktan sonra, bu tür fonksiyonları demet işleme kurallarına göre istediğiniz şekilde manipüle edebilirsiniz.

Peki böyle bir fonksiyon tanımlamak ne işimize yarar?

Mesela bu yapıyı kullanarak şöyle bir fonksiyon yazabilirsiniz:

defçarp(*sayılar):sonuç=1foriinsayılar:sonuç*=iprint(sonuç)

Bu fonksiyon kendisine verilen bütün parametreleri birbiriyle çarpar. Örneğin:

Bu kodun çıktısı 24 olacaktır. Gördüğünüz gibi, fonksiyonumuza istediğimiz sayıda parametre vererek bu sayıların birbiriyle çarpılmasını sağlayabiliyoruz.

Aslında burada kullandığımız * işareti size hiç yabancı değil. Hatırlarsanız fonksiyonundan bahsederken şuna benzer bir kullanım örneği vermiştik:

>>> print(*'TBMM',sep='.')T.B.M.M

Burada * işareti, eklendiği parametreyi öğelerine ayırıyor. sep parametresi ise * işaretinin birbirinden ayırdığı öğelerin arasına birer ‘.’ karakteri ekliyor.

Bu işaretin etkilerini şu örneklerde daha net görebilirsiniz:

>>> liste=["Ahmet","Mehmet","Veli"]>>> print(*liste)Ahmet Mehmet Veli>>> sözlük={"a":1,"b":2}>>> print(*sözlük)a b

Gördüğünüz gibi, * işareti herhangi bir öğeyi alıp, bunu parçalarına ayırıyor. İşte bu * işaretini fonksiyon tanımlarken kullandığımızda ise bu işlemin tam tersi gerçekleşiyor. Yani fonksiyon tanımında parametrenin soluna * getirdiğimizde, bu fonksiyon çağrılırken verilen argümanlar tek bir değişken içinde bir demet olarak toplanıyor. Zaten bu konunun başında verdiğimiz şu örnekte de bu durum açıkça görünüyor:

deffonksiyon(*parametreler):print(parametreler)fonksiyon(1,2,3,4,5)

Bu fonksiyonu çağırdığımızda şu çıktı veriliyor:

Aynen söylediğimiz gibi, adlı fonksiyona argüman olarak verdiğimiz her bir öğenin (1, 2, 3, 4, 5) tek bir demet içinde toplandığını görüyorsunuz.

Yıldızlı parametreler, tanımladığınız fonksiyonun parametre sayısını herhangi bir şekilde sınırlamak istemediğiniz durumlarda çok işinize yarar.

Elbette * işaretiyle birlikte kullanacağınız parametrenin adı olarak, Python’ın değişken adlandırma kurallarına uygun bütün kelimeleri belirleyebilirsiniz. Mesela biz yukarıda ‘parametreler’ adını tercih ettik. Ama Python dünyasında * işaretiyle birlikte kullanılacak parametrenin adı geleneksel olarak, ‘argümanlar’ anlamında ‘args’tır. Yani Python programcıları genellikle yukarıdaki gibi bir fonksiyonu şöyle tanımlar:

deffonksiyon(*args)

* işareti ile birlikte kullanılacak parametrenin adını ‘args’ yapmak bir zorunluluk olmamakla birlikte, başka Python programcılarının kodlarınızı daha kolay anlayabilmesi açısından bu geleneği devam ettirmenizi tavsiye ederim. Yazdığımız kodlarda Python programlama dilinin geleneklerine bağlı kalmak çoğunlukla iyi bir alışkanlıktır.

Rastgele Sayıda İsimli Parametre Belirleme¶

Bir önceki başlık altında, fonksiyon tanımlarken rastgele sayıda isimsiz parametrelerin nasıl belirleneceğini tartıştık. Aynı bu şekilde, rastgele sayıda isimli parametre belirlemek de mümkündür.

Örneğin:

deffonksiyon(**parametreler):print(parametreler)fonksiyon(isim="Ahmet",soyisim="Öz",meslek="Mühendis",şehir="Ankara")

Bu kodları çalıştırdığımızda şöyle bir çıktı alıyoruz:

{'isim':'Ahmet','soyisim':'Öz','meslek':'Mühendis','şehir':'Ankara'}

Gördüğünüz gibi, fonksiyonu tanımlarken parametremizin sol tarafına yerleştirdiğimiz ** işareti, bu fonksiyonu çağırırken yazdığımız isimli parametrelerin bize bir sözlük olarak verilmesini sağlıyor. Bu yapının bize bir sözlük verdiğini bildikten sonra, bunu sözlük veri tipinin kuralları çerçevesinde istediğimiz şekilde evirip çevirebiliriz.

Peki bu araç ne işimize yarar?

Hatırlarsanız bu bölümün en başında adlı şöyle bir fonksiyon tanımlamıştık:

defkayıt_oluştur(isim,soyisim,işsis,şehir):print("-"*30)print("isim : ",isim)print("soyisim : ",soyisim)print("işletim sistemi: ",işsis)print("şehir : ",şehir)print("-"*30)

Bu fonksiyon bize toplam dört adet parametre kullanarak, isim, soyisim, işletim sistemi ve şehir bilgilerinden meydana gelen bir kayıt oluşturma imkanı sağlıyor. Bu fonksiyonda kullanıcının girebileceği bilgiler sınırlı. Ama bir de şöyle bir fonksiyon yazdığımızı düşünün:

defkayıt_oluştur(**bilgiler):print("-"*30)foranahtar,değseafoodplus.info():print("{:<10}: {}".format(anahtar,değer))print("-"*30)kayıt_oluştur(ad="Fırat",soyad="Özgül",şehir="İstanbul",tel="")

Bu fonksiyonu çalıştırdığımızda şu çıktıyı alacağız:

telad:Fıratşehir:İstanbulsoyad:Özgül

Gördüğünüz gibi, ** işaretlerini kullanmamız sayesinde hem adlarını hem de değerlerini kendimiz belirlediğimiz bir kişi veritabanı oluşturma imkanı elde ediyoruz. Üstelik bu veritabanının, kişiye ait kaç farklı bilgi içereceğini de tamamen kendimiz belirleyebiliyoruz.

Tıpkı * işaretlerinin betimlediği parametrenin geleneksel olarak ‘args’ şeklinde adlandırılması gibi, ** işaretlerinin betimlediği parametre de geleneksel olarak ‘kwargs’ şeklinde adlandırılır. Dolayısıyla yukarıdaki gibi bir fonksiyonu Python programcıları şöyle tanımlar:

defkayıt_oluştur(**kwargs)

** işaretli parametreler pek çok farklı durumda işinize yarayabilir veya işinizi kolaylaştırabilir. Mesela * ve ** işaretlerini kullanarak şöyle bir program yazabilirsiniz:

defkarşılık_bul(*args,**kwargs):forsözcükinargs:ifsözcükinkwargs:print("{} = {}".format(sözcük,kwargs[sözcük]))else:print("{} kelimesi sözlükte yok!".format(sözcük))sözlük={"kitap":"book","bilgisayar":"computer","programlama":"programming"}karşılık_bul("kitap","bilgisayar","programlama","fonksiyon",**sözlük)

Burada tanımladığımız adlı fonksiyon, kendisine verilen parametreleri (*args), bir sözlük içinde arayarak (**sözlük) karşılıklarını bize çıktı olarak veriyor. Eğer verilen parametre sözlükte yoksa, ilgili kelimenin sözlükte bulunmadığı konusunda da bizi bilgilendiriyor.

adlı fonksiyonu nasıl tanımladığımıza çok dikkat edin. Parametre listesi içinde belirttiğimiz *args ifadesi sayesinde, fonksiyonu kullanacak kişiye, istediği sayıda isimsiz parametre girme imkanı tanıyoruz. **kwargs parametresi ise kullanıcıya istediği sayıda isimli parametre girme olanağı veriyor.

Esasında yukarıdaki kod *args ve **kwargs yapıları açısından ucuz bir örnektir. Bu yapılar için daha nitelikli bir örnek verelim…

Bildiğiniz gibi fonksiyonu sınırsız sayıda isimsiz parametre ve buna ek olarak birkaç tane de isimli parametre alıyor. Bu fonksiyonun alabildiği isimli parametrelerin sep, end, file ve flush adlı parametreler olduğunu biliyorsunuz. Yine bildiğiniz gibi, sep parametresi fonksiyonuna verilen isimsiz parametrelerin her birinin arasına hangi karakterin geleceğini; end parametresi ise bu parametrelerin en sonuna hangi karakterin geleceğini belirliyor. Bizim amacımız bu fonksiyona bir de start adında isimli bir parametre ekleyerek fonksiyonunun işlevini genişleten başka bir fonksiyon yazmak. Bu yeni parametre, karakter dizilerinin en başına hangi karakterin geleceğini belirleyecek.

Şimdi bu amacımızı gerçekleştirecek kodlarımızı yazalım:

defbas(*args,start='',**kwargs):foröğeinargs:print(start+öğe,**kwargs)bas('öğe1','öğe2','öğe3',start="#.")

fonksiyonunun işlevini genişleten yeni fonksiyonumuzun adı . Bu fonksiyon her bakımdan fonksiyonu ile aynı işlevi görecek. Ancak fonksiyonu, fonksiyonuna ek olarak, sahip olduğu start adlı bir isimli parametre sayesinde, kendisine verilen parametrelerin en başına istediğimiz herhangi bir karakteri ekleme olanağı da verecek bize.

fonksiyonunun ilk parametresi olan *args sayesinde kullanıcıya istediği kadar parametre verme imkanı tanıyoruz. Daha sonra da ilave start parametresini tanımlıyoruz. Bu parametrenin öntanımlı değeri boş bir karakter dizisi. Yani eğer kullanıcı bu parametrenin değerine herhangi bir şey yazmazsa, *args kapsamında verilen parametreler üzerinde hiçbir değişiklik yapmıyoruz. Bunun ardından gelen **kwargs parametresi ise fonksiyonunun halihazırda sahip olduğu sep, end, file ve flush parametrelerinin fonksiyonunda da aynı şekilde kullanılmasını sağlıyor. **kwargs şeklinde bir tanımlama sayesinde, fonksiyonunun isimli parametrelerini tek tek belirtip tanımlamak zorunda kalmıyoruz:

defbas(*args,start='',**kwargs):foröğeinargs:print(start+öğe,**kwargs)f=open("seafoodplus.info","w")bas('öğe1','öğe2','öğe3',start="#.",end="",file=f)

Eğer elimizde **kwargs gibi bir imkan olmasaydı yukarıdaki fonksiyonu şu şekilde tanımlamamız gerekirdi:

importsysdefbas(*args,start='',sep=' ',end='\n',file=seafoodplus.info,flush=False):foröğeinargs:print(start+öğe,sep=sep,end=end,file=file,flush=flush)

Gördüğünüz gibi, fonksiyonunun bütün isimli parametrelerini ve bunların öntanımlı değerlerini tanımlamak zorunda kaldık. Eğer günün birinde Python geliştiricileri fonksiyonuna bir başka isimli parametre daha eklerse, yukarıdaki fonksiyonu ilgili yeniliğe göre elden geçirmemiz gerekir. Ama **kwargs yapısını kullandığımızda, fonksiyonuna Python geliştiricilerince eklenecek bütün parametreler bizim fonksiyonumuza da otomatik olarak yansıyacaktır…

return Deyimi¶

Bu bölümde adlı bir deyimden söz edeceğiz. Özellikle Python programlama dilini öğrenmeye yeni başlayanlar bu deyimin ne işe yaradığını anlamakta zorlanabiliyor. Biz burada bu deyimi anlaşılır hale getirebilmek için elimizden geleni yapacağız. Öncelikle çok basit bir örnek verelim:

defismin_ne():isim=input("ismin ne? ")print(isim)

Bu çok basit bir fonksiyon. Bu fonksiyonu nasıl çağıracağımızı biliyoruz:

Fonksiyonu bu şekilde çağırdıktan sonra, fonksiyon tanımında yer alan fonksiyonu sayesinde kullanıcıya ismi sorulacak ve verdiği cevap ekrana basılacaktır.

Yukarıdaki fonksiyonun tek işlevi kullanıcıdan aldığı isim bilgisini ekrana basmaktır. Aldığınız bu veriyi başka yerlerde kullanamazsınız. Bu fonksiyonu çağırdığınız anda kullanıcıya ismi sorulacak ve alınan cevap ekrana basılacaktır. Ancak siz, tanımladığınız fonksiyonların tek görevinin bir veriyi ekrana basmak olmasını istemeyebilirsiniz.

Örneğin yukarıdaki fonksiyon yardımıyla kullanıcıdan ismini aldıktan sonra, bu isim bilgisini başka bir karakter dizisi içinde kullanmak isteyebilirsiniz. Diyelim ki amacınız fonksiyonuyla aldığınız ismi şu karakter dizisi içine aşağıdaki şekilde yerleştirmek:

Bildiğimiz yöntemi kullanarak bu amacımızı gerçekleştirmeye çalışalım:

print("Merhaba {}. Nasılsın?".format(ismin_ne()))

Buradan şöyle bir çıktı alıyoruz:

ismin ne? FıratFıratMerhaba None. Nasılsın?

Gördüğünüz gibi, istediğimiz şeyi elde edemiyoruz. Çünkü dediğimiz gibi, yukarıdaki fonksiyonun tek görevi kullanıcıdan aldığı çıktıyı ekrana basmaktır. Bu fonksiyondan gelen çıktıyı başka yerde kullanamayız. Eğer kullanmaya çalışırsak yukarıdaki gibi hiç beklemediğimiz bir sonuç alırız.

Bu arada, çıktıda None diye bir şey gördüğünüze dikkat edin. Yukarıdaki fonksiyonu şu şekilde çağırarak bunu daha net görebilirsiniz:

Buradan şu çıktıyı alıyoruz:

ismin ne? FıratFıratNone

Bu çıktının ne anlama geldiğini birazdan açıklayacağız. Ama öncelikle başka bir konudan söz edelim.

Biraz önce söylediğimiz gibi, yukarıda tanımladığımız adlı fonksiyonun tek görevi kullanıcıdan aldığı isim bilgisini ekrana basmaktır. Şimdi bu fonksiyonu bir de şöyle tanımlayalım:

defismin_ne():isim=input("ismin ne? ")returnisim

Şimdi de bu fonksiyonu çağıralım:

Gördüğünüz gibi, fonksiyonu çağırdığımızda yalnızca fonksiyon gövdesindeki fonksiyonu çalıştı, ama bu fonksiyondan gelen veri ekrana çıktı olarak verilmedi. Çünkü biz burada herhangi bir ekrana basma (‘print’) işlemi yapmadık. Yaptığımız tek şey isim adlı değişkeni ‘döndürmek’.

Peki bu ne anlama geliyor?

return kelimesi İngilizcede ‘iade etmek, geri vermek, döndürmek’ gibi anlamlar taşır. İşte yukarıdaki örnekte de deyiminin yaptığı iş budur. Yani bu deyim bize fonksiyondan bir değer ‘döndürür’.

Eğer tanımladığımız bir fonksiyonda deyimini kullanarak herhangi bir değer döndürmezsek, Python fonksiyondan hususi bir değerin döndürülmediğini göstermek için ‘None’ adlı bir değer döndürür… İşte yukarıda tanımladığımız ilk fonksiyonunu şeklinde çağırdığımızda ekranda None değerinin görünmesinin nedeni budur.

Peki bir fonksiyon içinde herhangi bir veriyi ekrana basmayıp deyimi yardımıyla döndürmemizin bize ne faydası var?

Aslında bunun cevabı çok açık. Bir fonksiyon içinde bir değeri döndürmek yerine ekrana bastığınızda o fonksiyonun işlevini alabildiğine kısıtlamış oluyorsunuz. Fonksiyonunuzun tek işlevi bir değeri ekrana basmak oluyor. Şu örnekte de gösterdiğimiz gibi, bu değeri daha sonra başka ortamlarda kullanamıyoruz:

defismin_ne():isim=input("ismin ne? ")print(isim)print("Merhaba {}. Nasılsın?".format(ismin_ne()))

Ama eğer, mesela yukarıdaki fonksiyonda isim değişkenini basmak yerine döndürürsek işler değişir:

defismin_ne():isim=input("ismin ne? ")returnisimprint("Merhaba {}. Nasılsın?".format(ismin_ne()))

Bu kodları çalıştırdığımızda şu çıktıyı alıyoruz:

ismin ne? Fırat Merhaba Fırat. Nasılsın?

Gördüğünüz gibi, istediğimiz çıktıyı rahatlıkla elde ettik. adlı fonksiyondan isim değerini döndürmüş olmamız sayesinde bu değerle istediğimiz işlemi gerçekleştirebiliyoruz. Yani bu değeri sadece ekrana basmakla sınırlamıyoruz kendimizi. Hatta fonksiyondan döndürdüğümüz değeri başka bir değişkene atama imkanına dahi sahibiz bu şekilde:

ad=ismin_ne()print(ad)

Eğer fonksiyondan değer döndürmek yerine bu değeri ekrana basmayı tercih etseydik yukarıdaki işlemi yapamazdık.

deyimiyle ilgili son bir şey daha söyleyelim…

Bu deyim, içinde bulunduğu fonksiyonun çalışma sürecini kesintiye uğratır. Yani deyimini kullandığınız satırdan sonra gelen hiçbir kod çalışmaz. Basit bir örnek verelim:

deffonk():print(3)returnprint(5)fonk()

Bu kodları çalıştırdığınızda yalnızca satırının çalıştığını, satırına ise hiç ulaşılmadığını göreceksiniz. İşte bu durumun sebebi, Python’ın kodları satırından itibaren okumayı bırakmasıdır. Bu özellikten çeşitli şekillerde yararlanabilirsiniz. Örneğin:

deffonk(n):ifn<0:return'eksi değerli sayı olmaz!'else:returnnf=fonk(-5)print(f)

Burada eğer fonksiyona parametre olarak eksi değerli bir sayı verilirse Python bize bir uyarı verecek ve fonksiyonun çalışmasını durduracaktır.

Örnek bir Uygulama¶

Gelin isterseniz buraya kadar öğrendiklerimizi kullanarak örnek bir uygulama yazalım. Bir yandan da yeni şeyler öğrenerek bilgimize bilgi katalım.

Amacımız belli miktarda ve belli aralıkta rastgele sayılar üreten bir program yazmak. Örneğin programımız şu şekilde altı adet rastgele sayı üretebilecek:

,,,24,91,

Ancak programımız bu sayıları üretirken her sayıdan yalnızca bir adet üretecek. Yani aynı seride bir sayıdan birden fazla bulunamayacak.

Dilerseniz öncelikle kodlarımızı görelim:

importrandomdefsayı_üret(başlangıç=0,bitiş=,adet=6):sayılar=set()whilelen(sayılar)<adet:sayıseafoodplus.info(seafoodplus.infonge(başlangıç,bitiş))returnsayılar

Esasında bu kodların (neredeyse) tamamını anlayabilecek kadar Python bilgisine sahipsiniz. Burada anlamamış olabileceğiniz tek şey random modülüdür. O yüzden gelin isterseniz bu modülden biraz söz edelim.

Biz henüz modül kavramını bilmiyoruz. Ama buraya gelene kadar birkaç konu altında modüllerle ilgili bazı örnekler de yapmadık değil. Örneğin şimdiye kadar yazdığımız programlardan öğrendiğimiz kadarıyla Python’da os ve sys adlı iki modülün bulunduğunu, bu modüllerin içinde, program yazarken işimize yarayacak pek çok değişken ve fonksiyon bulunduğunu ve bu fonksiyonları programlarımızda kullanabilmek için ilkin bu modülleri içe aktarmamız gerektiğini biliyoruz. İşte tıpkı os ve sys gibi, random da Python programlama dili bünyesinde bulunan modüllerden biridir. Bu modülün içinde, rastgele sayılar üretmemizi sağlayacak bazı fonksiyonlar bulunur. İşte de bu fonksiyonlardan biridir. Dilerseniz bu fonksiyonun nasıl kullanıldığını anlamak için etkileşimli kabukta birkaç deneme çalışması yapalım.

random modülünün içindeki araçları kullanabilmek için öncelikle bu modülü içe aktarmalıyız:

>>> importrandom

Acaba bu modülün içinde neler varmış?

>>> dir(random)['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random','SG_MAGICCONST', 'SystemRandom', 'TWOPI', '_BuiltinMethodType','_MethodType', '_Sequence', '_Set', '__all__', '__builtins__','__cached__', '__doc__', '__file__', '__initializing__','__loader__', '__name__', '__package__', '_acos', '_ceil','_cos', '_e', '_exp', '_inst', '_log', '_pi', '_random', '_sha','_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn','betavariate', 'choice', 'expovariate', 'gammavariate', 'gauss','getrandbits', 'getstate', 'lognormvariate', 'normalvariate','paretovariate', 'randint', 'random', 'randrange', 'sample','seed', 'setstate', 'shuffle', 'triangular', 'uniform','vonmisesvariate', 'weibullvariate']

Gördüğünüz gibi bu modülün içinde epey araç var. Gelin isterseniz bu araçlardan en sık kullanılanlarını tanıyalım.

Örneğin random modülü içinde bulunan adlı fonksiyon herhangi bir dizi içinden istediğimiz sayıda rastgele numune almamızı sağlar:

>>> liste=["ahmet","mehmet","sevgi","sevim","selin","zeynep","selim"]>>> seafoodplus.info(liste,2)['sevim', 'ahmet']

Gördüğünüz gibi, yedi kişilik bir isim listesinden 2 adet rastgele numune aldık. Aynı işlemi tekrarlayalım:

>>> seafoodplus.info(liste,2)['sevgi', 'zeynep']>>> seafoodplus.info(liste,5)['selin', 'zeynep', 'ahmet', 'selim', 'mehmet']

Numune alma işlemi tamamen rastgeledir. Ayrıca gördüğünüz gibi, listeden istediğimiz sayıda numune alabiliyoruz.

random modülü içinde bulunan adlı başka bir fonksiyon, bir dizi içindeki öğelerin sırasını rastgele bir şekilde karıştırmamızı sağlar:

>>> liste=["ahmet","mehmet","sevgi","sevim", "selin","zeynep","selim"]>>> seafoodplus.infoe(liste)

fonksiyonu liste öğelerini yine aynı liste içinde değiştirdi. Değişikliği görmek için listeyi ekrana basabilirsiniz:

>>> liste['selim', 'selin', 'ahmet', 'mehmet','sevim', 'sevgi', 'zeynep']

random modülü içinde bulunan bir başka fonksiyon ise fonksiyonudur. Bu fonksiyon, belli bir aralıkta rastgele sayılar üretmemizi sağlar:

>>> seafoodplus.infonge(0,)

Burada 0 ile arasında rastgele bir sayı ürettik.

Gördüğünüz gibi random son derece faydalı olabilecek bir modüldür. Dilerseniz şimdi random modülünü bir kenara bırakıp kodlarımıza geri dönelim:

importrandomdefsayı_üret(başlangıç=0,bitiş=,adet=6):sayılar=set()whilelen(sayılar)<adet:sayıseafoodplus.info(seafoodplus.infonge(başlangıç,bitiş))returnsayılar

Burada ilk satırın ne iş yaptığını öğrendik. Bu satır yardımıyla random modülünü içe aktarıyoruz.

Sonraki satırda fonksiyonumuzu tanımlamaya başlıyoruz:

defsayı_üret(başlangıç=0,bitiş=,adet=6)

Fonksiyonumuzun adı sayı_üret. Bu fonksiyon toplam üç farklı parametre alıyor. Bunlar başlangıç, bitiş ve adet. Dikkat ederseniz bu parametrelerin her birinin bir varsayılan değeri var. Dolayısıyla fonksiyonu parametresiz olarak çağrıldığında bu üç parametre öntanımlı değerlerine sahip olacaktır.

Gelelim fonksiyon gövdesine…

İlk olarak sayılar adlı bir küme tanımlıyoruz.

Bildiğiniz gibi, kümeler içinde öğeler her zaman tektir. Yani bir küme içinde aynı öğeden yalnızca bir adet bulunabilir. Kümelerin bu özelliği bizim yazdığımız program için oldukça uygun. Çünkü biz de ürettiğimiz rastgele sayıların benzersiz olmasını istiyoruz. Bu benzersizliği sağlayabilecek en uygun veri tipi kümelerdir.

Bir sonraki satırda bir döngüsü görüyoruz:

whilelen(sayılar)<adet:sayıseafoodplus.info(seafoodplus.infonge(başlangıç,bitiş))

Bu döngüye göre, sayılar değişkeninin uzunluğu adet parametresinin değerinden az olduğu müddetçe, sayılar adlı değişkene başlangıç ve bitiş parametrelerinin gösterdiği değerler arasından rastgele sayılar eklemeye devam edeceğiz. Örneğin kullanıcı fonksiyonumuzu parametresiz olarak çağırdıysa, yukarıdaki döngü şu şekilde işleyecektir:

whilelen(sayılar)<6:sayıseafoodplus.info(seafoodplus.infonge(0,))

Buna göre, sayılar değişkeninin uzunluğu 6’dan az olduğu müddetçe bu değişkene 0 ile arasında rastgele sayılar eklemeye devam edeceğiz. Böylelikle sayılar değişkeni içinde birbirinden farklı toplam 6 sayı olmuş olacak.

Fonksiyonun son satırında ise şu kodu görüyoruz:

Bu kod yardımıyla, belirtilen miktardaki sayıları tutan sayılar adlı değişkeni fonksiyondan döndürüyoruz. Yani fonksiyonumuz dış dünyaya sayılar adlı bir değişken veriyor… Bu değişkeni bu şekilde döndürdükten sonra istediğimiz gibi kullanabiliriz. Mesela:

foriinrange():print(sayı_üret())

Buradan şuna benzer bir çıktı alacaksınız:

{34,,,,58,}{41,,,,,29}{,,,,,}{1,,,,,}{,,12,,,}{,34,,,,}{,,,,,63}{,,,,81,}{36,,21,,,}{,,,,,}{,38,,,59,}{0,2,42,,,60}{48,,,80,,}{,,,35,,}

Gördüğünüz gibi, fonksiyonunu kullanarak, her biri 6 öğeden oluşan adet sayı listesi elde ettik. Biz yukarıda bu fonksiyonu parametresiz olarak çalıştırdığımız için, Python başlangıç, bitiş ve adet parametrelerinin öntanımlı değerlerini kullandı (sırasıyla 0, ve 6).

İstersek biz fonksiyonumuzu farklı parametrelerle çağırabiliriz:

print(sayı_üret(0,,10))

Bu kodlar bize 0 ile arasından 10 adet rastgele sayı seçer:

{3,4,9,11,13,47,50,53,54,61}

Eğer çıktının küme parantezleri arasında görünmesini istemiyorsanız elbette çıktıyı keyfinize göre biçimlendirebilirsiniz:

print(*sayı_üret(,,20),sep='-')

Bu şekilde, ile arası sayılardan rastgele 20 adet seçip her bir sayının arasına bir tane - işareti yerleştirdik:

Fonksiyonların Kapsamı ve global Deyimi¶

Elimizde şöyle bir kod olduğunu düşünelim:

x=0deffonk():x=1returnx

Bu kodlarda, fonksiyonun dışında x adlı bir değişken var. Fonksiyonun içinde de yine x adını taşıyan başka bir değişken var. Fonksiyonumuzun görevi bu x değişkenini döndürmek.

Bu noktada size şöyle bir soru sormama izin verin: Acaba fonksiyon içinde tanımladığımız x değişkeni, fonksiyon dışındaki x değişkeninin değerini değiştiriyor mu? Bu sorunun cevabını şu kodlarla verelim:

x=0deffonk():x=1returnxprint('fonksiyon içindeki x: ',fonk())print('fonksiyon dışındaki x: ',x)

Bu kodları çalıştırdığımızda şu çıktıyı alacağız:

fonksiyoniçindekix:1fonksiyondışındakix:0

Gördüğünüz gibi fonksiyon içindeki ve fonksiyon dışındaki aynı adlı değişkenler birbirine karışmıyor. Bunun sebebi, Python’daki ‘isim alanı’ (namespace) adlı bir kavramdır.

Peki isim alanı ne demek?

Python’da değişkenlerin, fonksiyonların ve daha sonra göreceğiniz gibi sınıfların bir kapsamı vardır. Bu kapsama Python’da ‘isim alanı’ adı verilir. Dolayısıyla Python’da her nesnenin, geçerli ve etkin olduğu bir isim alanı bulunur. Örneğin yukarıdaki kodlarda fonksiyon dışındaki x değişkeni ana isim alanında yer alan ‘global’ bir değişkendir. Fonksiyon içindeki x değişkeni ise değişkeninin isim alanı içinde yer alan ‘lokal’ bir değişkendir. Bu iki değişken, adları aynı da olsa, birbirlerinden farklı iki nesnedir.

Bir de şu örneklere bakalım:

x=[]print('x\'in ilk hali:',x)defdeğiştir():print('x\'i değiştiriyoruz')seafoodplus.info(1)returnxdeğiştir()print('x\'in son hali: ',x)

Burada ise daha farklı bir durum söz konusu. Fonksiyon içinde metodunu kullanarak yaptığımız ekleme işlemi fonksiyon dışındaki listeyi de etkiledi. Peki ama bu nasıl oluyor?

Python herhangi bir nesneye göndermede bulunduğumuzda, yani o nesnenin değerini talep ettiğimizde aradığımız nesneyi ilk önce mevcut isim alanı içinde arar. Eğer aranan nesneyi mevcut isim alanı içinde bulamazsa yukarıya doğru bütün isim alanlarını tek tek kontrol eder.

Birkaç örnek verelim:

deffonk():print(x)fonk()

Tahmin edebileceğiniz gibi, bu kodlar şu hatayı verecektir:

Traceback(mostrecentcalllast):File"seafoodplus.info",line4,in<module>fonk()File"seafoodplus.info",line2,infonkprint(x)NameError:globalname'x'isnotdefined

Bu hatanın sebebi, x adlı bir değişkenin tanımlanmamış olmasıdır. Bu hatayı gidermek için şöyle bir kod yazabiliriz:

x=0deffonk():print(x)fonk()

Bu kod global alandaki x değişkeninin değerini verecektir.

Yukarıdaki örnekte, biz ile x’in değerini sorguladığımızda Python öncelikle adlı fonksiyonun isim alanına baktı. Orada x’i bulamayınca bu kez global alana yönelip, orada bulduğu x’in değerini yazdırdı.

Bu durumu daha net anlayabilmek için şu kodları inceleyelim:

x=0deffonk():x=10print(x)fonk()print(x)

Bu kodları çalıştırdığımızda 10 çıktısını alırız. Çünkü Python, dediğimiz gibi, öncelikle mevcut isim alanını kontrol ediyor. x değişkenini mevcut isim alanında bulduğu için de global alana bakmasına gerek kalmıyor.

Yalnız burada dikkat etmemiz gereken bazı şeyler var.

Dediğimiz gibi, global isim alanındaki nesnelerin değerini lokal isim alanlarından sorgulayabiliyoruz. Ancak istediğimiz şey global isim alanındaki nesnelerin değerini değiştirmekse bazı kavramlar arasındaki farkları iyi anlamamız gerekiyor.

Python’da bir nesnenin değerini değiştirmekle, o nesneyi yeniden tanımlamak farklı kavramlardır.

Eğer bir nesne değiştirilebilir bir nesne ise, o nesnenin değerini, lokal isim alanlarından değiştirebilirsiniz:

x=set()deffonk():seafoodplus.info(10)returnxprint(fonk())

Ama eğer bir nesne değiştirilemez bir nesne ise, o nesnenin değerini zaten normalde de değiştiremezsiniz. Değiştirmiş gibi yapmak için ise o nesneyi yeniden tanımlamanız gerektiğini biliyorsunuz:

>>> isim='Fırat'>>> isim+=' Özgül'>>> print(isim)Fırat Özgül

Burada yaptığımız şey, karakter dizisinin değerini değiştirmekten ziyade bu karakter dizisini yeniden tanımlamaktır. Çünkü bildiğiniz gibi karakter dizileri değiştirilemeyen veri tipleridir.

İşte karakter dizileri gibi değiştirilemeyen nesneleri, lokal isim alanlarında değiştiremeyeceğiniz gibi, yeniden tanımlayamazsınız da…

isim='Fırat'deffonk():isim+=' Özgül'returnisimprint(fonk())

Bu kodları çalıştırdığınızda Python size bir hata mesajı gösterecektir.

Aynı durum değiştirilebilir nesneler için de geçerlidir:

isim_listesi=[]deffonk():isim_listesi+=['Fırat Özgül','Orçun Kunek']returnisim_listesiprint(fonk())

Değiştirilebilen bir veri tipi olan listeleri, fonksiyon içinde yeniden tanımlayamazsınız. Ancak tabii isterseniz listeleri değişikliğe uğratabilirsiniz:

isim_listesi=[]deffonk():isim_seafoodplus.info(['Fırat Özgül','Orçun Kunek'])returnisim_listesiprint(fonk())

Bu kodlar düzgün bir şekilde çalışıp, fonksiyon dışındaki isim_listesi adlı listeyi değişikliğe uğratacaktır. Ancak şu kodlar hata verecektir:

isim_listesi=[]deffonk():isim_listesi+=['Fırat Özgül','Orçun Kunek']returnisim_listesiprint(fonk())

İşte Python programlama dili bu tür durumlar için çözüm olacak bir araç sunar bize. Bu aracın adı global.

Gelin isterseniz bu global adlı deyimin nasıl kullanılacağına bakalım önce…

Şu kodların hata vereceğini biliyorsunuz:

isim='Fırat'deffonk():isim+=' Özgül'returnisimprint(fonk())

Ama bu kodlara şöyle bir ekleme yaparsanız işler değişir:

isim='Fırat'deffonk():globalisimisim+=' Özgül'returnisimprint(fonk())

Burada adlı fonksiyonun ilk satırında şöyle bir kod görüyoruz:

İşte bu satır, isim adlı değişkenin global alana taşınmasını sağlıyor. Böylece global alanda bulunan isim adlı değişkeni değişikliğe uğratabiliyoruz.

global deyimi her ne kadar ilk bakışta çok faydalı bir araçmış gibi görünse de aslında programlarımızda genellikle bu deyimi kullanmaktan kaçınmamız iyi bir fikir olacaktır. Çünkü bu deyim aslında global alanı kirletmemize neden oluyor. Global değişkenlerin lokal isim alanlarında değişikliğe uğratılması, eğer dikkatsiz davranırsanız programlarınızın hatalı çalışmasına yol açabilir.

Python fonksiyonlar def komutu ile kodlanır ve kısaca belirli bir görevi yerine getiren, girdi alan ve çıktı veren birimler olarak tanımlanabilir.

Fonksiyonun Özellikleri

Fonksiyonlar prosedürel programlamanın temelini oluşturur. En belirgin avantajlardan biri, bir programın daha küçük parçalara bölünmesidir. Python fonksiyonlar için özellikler üç alt başlık altında incelenmiştir.

Modüler Programlama

Modüler, “takılıp sökülebilen, ihtiyaca göre kullanım alanı değiştirilebilen, kullanıcı isteklerine göre şekillendirilebilen” anlamı taşır. Programlamada da benzer bir manada kullanılmaktadır: Eğer bir program, farklı bölümlerin her biri belirli bir görevi yerine getirecek şekilde küçük parçalara bölünürse, her bölüm gereksinime göre çağrılabilir.

Kodun Yeniden Kullanılabilirliği

Bir fonksiyon birçok kez çağrılabilir. Böylece aynı kodun tekrar tekrar yazılması önlenmiş olduğu için programın uzunluğu azalır ve daha verimli bir kodlama deneyimi sağlar.

Yönetilebilirlik

Daha büyük bir görevi daha küçük işlevlere bölmek, programı yönetilebilir hale getirir. Hataları bulmak kolaylaşır ve bu nedenle programı güvenilir hale getirir. Bir fonksiyonda yerel optimizasyon yapmak da kolaylaşıyor. Özetlemek gerekirse, yönetilebilirlik sayesinde hata ayıklama (debugging) kolaylaşır ve haliyle de verimli bir kodlama deneyimi sağlar.

Python Fonksiyonlar

Nasıl ki gündelik hayatta daha büyük bir görevi yerine getirmek için daha küçük, daha yönetilebilir görevlere bölünüyorsa programlamada da fonksiyonlar benzer işlevi yerine getirmek için kullanılmaktadır.

Fonksiyonlar programlamanın olmazsa olmazlarındandır ve C, C++, Java, C# gibi diğer programlama dillerine hakim olanlar, Python ile de fonksiyonların fikrine ve kullanımına aşina olacaktır. Zaten halihazırda önceki derslerimizde de print (), type () gibi pek çok “fonksiyonu” aktif bir şekilde kullanmıştık.

Python’da builtin functions olarak bilinen ve Türkçeye gömülü fonksiyonlar olarak çevrilen print (), type () gibi daha niceleri Python geliştiricileri tarafından önceden tanımlanıp dile gömülü halde hizmetimize sunulmuş fonksiyonlardır.

Nasıl ki gömülü fonksiyonlar ile karmaşık işlemleri kolayca yapabiliyorsak programlamacı olarak bizler de kendi fonksiyonlarımızı tanımlayıp kullanabiliriz.

Python Fonksiyon Elemanları

Python’da bir fonksiyonun tanımı aşağıdakileri içerir:

Fonksiyonun adı

Bir işlevin adı, geçerli herhangi bir tanımlayıcıdır. Unutulmamalıdır ki bir fonksiyonun isminin anlamlı olması ve mümkünse fonksiyonun yapacağı görevi iletmesi gerekmektedir.

Parametre

Parametre listesi (virgülle ayrılmış) fonksiyon adından sonra parantez içinde verilmiştir. Parametreler temel olarak fonksiyonun girdileridir.

Parametre, fonksiyon tanımında parantez içinde listelenen değişkenken, argüman ise çağrıldığında işleve gönderilen değerdir.

Fonksiyonun Gövdesi

Fonksiyonun gövdesi, fonksiyon tarafından gerçekleştirilecek görevi uygulayan kodu içerir.

Python Fonksiyon elemanları (def)

Python Fonksiyon Tanımlama

Python’da fonksiyon tanımlarken def komutu kullanılmaktadır. Aşağıdaki örneği inceleyin:

 

defbenim_fonksiyonum():

  print("Ben bir fonksiyonum!")

Kodu çalıştır.

Yukarıdaki örnekte de fark edileceği üzere fonksiyonumuzu tanımlamak için kullandığımız def komutundan sonra fonksiyonun adına yer verilir. Bu ad programlamacının kendi insiyatifine bırakılmıştır. Zira yukarıdaki örnekte de bu ad benim_fonksiyonum şeklinde kodlanmıştır.

Fonksiyonumuzu def ile tanımlayıp gerekli adlandırmaya yaptıktan sonra da parantez açılır ve varsa parametre (argüman) olarak bilinen veriler yazılır ve parantez kapatılır. Ardından çift nokta koyularak fonksiyon çağrıldığında çalışması istenen kodlar yazılmaya başlanır. Tabi çift nokta koyulduğu için girintili bir şekilde bu kodlar yazılır.

Diğer programlama dillerinde de olduğu gibi Python’da kodlar lineer bir şekilde yukarıdan aşağıya doğru okunmaktadır. Yani en üstteki koddan başlar soldan sağa, aşağıya doğru gider. Ancak fonksiyonlarla alakalı bilinmesi gereken öncelikli şeylerden birisi de fonksiyonlar çağrılmadığı müddetçe çalıştırılmaz.

Python Fonksiyon Çağırmak

Her ne kadar yukarıdaki örneğimizde tanımlamayı yapmış olsak da fonksiyonumuz çağrılmadığı için fonksiyon bloğu içine yazdığımız kodlar çalıştırılmayacaktır. Fonksiyonu çağırmak içinse fonksiyonun ismi parantezleriyle beraber yazılır:

 

defbenim_fonksiyonum():

  print("Ben bir fonksiyonum!")

  

benim_fonksiyonum()  

Kodu çalıştır.

Python Fonksiyon Çağırmak

Python’da Parametreler

Fonksiyonlarda bilgiler parametreler ve argümanlar vasıtasıyla iletilir. Parametre, fonksiyonu adlandırdıktan sonra parantez içinde olacak şekilde belirtilir. Parantez içindeki parametreler virgülle ayrılmak şartıyla istenilen sayıda kullanılabilmektedir.

Aşağıdaki örneği inceleyiniz:

 

deffonksiyonum(ad):

  print("Adınız: "+ad)

 

fonksiyonum("Python")

fonksiyonum("C++")

Kodu çalıştır.

Yukarıdaki örnekte de görüleceği üzere fonksiyon içerisine tek bir parametre girilmiştir. Belirtmek gerekir ki fonksiyon çağrılırken kaç sayıda parametre belirtilmişse o sayıda olması beklenir ve sıralı bir şekilde eşleşir. Örneğin, eğer bir fonksiyon üç parametre ile oluşturulduysa, çağırırken de ne eksik ne de fazla yine üç parametre ile çağrılmaktadır.

Aşağıdaki örneği inceleyiniz:

 

deffonksiyon(ad,soyad):

  print("Adınız: "+ad+", Soyadınız: "+soyad)

 

fonksiyon("Brad","Pitt")

Kodu çalıştır.

Yukarıdaki örnekte eğer ikiden farklı parametre verilseydi derleyici hata verirdi.

Değişken Sayıda Parametre Alabilen Fonksiyonlar

Eğer fonksiyonun kaç parametre alacağı ile alakalı kesin bir bilgi yoksa parametre adından önce bir * eklemek kafi olacaktır. Bu şekilde fonksiyon bir dizi argüman alacak ve buna göre öğelere erişebilecektir:

 

deffonksiyon(*diller):

  print("En kolay dil: "+diller&#91;2])

 

fonksiyon("C++","C","Python")

Kodu çalıştır.

Fonksiyonlarda Parametre Anahtarları Kullanmak

Parametreler, anahtar (key) = değer (value) şeklinde bir yapı ile pekala gönderilebilir. Böylesi durumlarda haliyle parametre sırası önemsiz olmaktadır:

 

deffonksiyon(dil3,dil2,dil1):

  print("En kolaay dil: "+dil3)

 

fonksiyon(dil1="C++",dil2="C",dil3="Python")

Kodu çalıştır.

Python Varsayılan Parametre Değeri Belirtmek

Python fonksiyon için parametre kullanılmadığı zaman geçerli olacak parametre değeri = değer şeklinde yazarak belirtilebili:

 

defprogramlama(dil  ="Python"):

  print("Programlama Dili: "+dil)

 

programlama("C++")

programlama("C")

programlama()

programlama("C#")

Kodu çalıştır.

Python return Deyimi

return kelimesi “iade etmek, geri vermek, döndürmek” gibi anlamlara gelmektedir ve fonksiyondan bir değer “döndürmek” için kullanılmaktadır.

  • return deyimi herhangi bir ifade içermiyorsa, None özel değeri döndürür
  • return deyiminin kullandığı satırdan sonra gelen hiçbir kod çalışmaz.
  • return deyimi ile döndürülmüş bir değer başka bir değişkene atanabilir.

Peki Python’da bir fonksiyon içinde herhangi bir veriyi ekrana basmayıp return deyimi yardımıyla döndürülmesinin ne gibi faydası var diye sorulacak olursa, döndürülen değerin daha sonra başka ortamlarda da kullanabilmesi şeklinde özetlenebilir:

 

deftopla(sayi1=10,sayi2=20):

    returnsayi1+sayi2

    

toplam=topla(,)    

print("Sonuç :",toplam)

Kodu çalıştır.

nest...

batman iftar saati 2021 viranşehir kaç kilometre seferberlik ne demek namaz nasıl kılınır ve hangi dualar okunur özel jimer anlamlı bayram mesajı maxoak 50.000 mah powerbank cin tırnağı nedir