BİL203U-PROGRAMLAMA II
Ünite 3: Fonksiyonlar
Giriş
Program yazarken yapılan işi daha küçük parçalara ayırmak hem kodun okunaklığını hem de bakımını daha kolay hale getirmektedir. Mantıksal çerçevede bölünen iş parçacıklarına fonksiyon adı verilmektedir. Programlarda kolaylık olması açısından daha önceden hazırlanmış, yapılan işe uygun şekilde dizayn edilmiş fonksiyonları barındıran paketler bulunmaktadır.
Python Fonksiyonları
Fonksiyonlar, belirli bir görevi yerine getiren kod bloklarına verilen isimdir. Fonksiyonlar, programları daha küçük ve modüler parçalara ayırmaya yardımcı olur. Program büyüdükçe fonksiyonlar, yazılan kodun daha düzenli ve yönetilebilir hale gelmesinde büyük rol oynamaktadır. Kod tekrarını önleyerek, kodun yeniden kullanılabilir hale getirilmesini sağlar. Fonksiyon gibi bir tanımlama yapılmak istendiğinde def anahtar kelimesi kullanılmaktadır.
Fonksiyon Sözdizimi:
def fonksiyon_adı(parametre(ler)): """docstring""" kod bloğu
def: Fonksiyon başlığının başlangıcını işaretleyen anahtar sözcüktür.
fonksiyon_adı: Fonksiyonu benzersiz şekilde tanımlamak için kullanılan bir tanımlamadır.
parametre(ler): Bir fonksiyona iletmek istediğimiz değerlerdir. İsteğe bağlı olarak kullanılır.
İki nokta üst üste (:): Fonksiyon başlığının sonunu işaretlemek için kullanılır.
docstring (Yorum satırı): Fonksiyonun parametreleri ve fonksiyonun görevini açıklamak için isteğe bağlı yazılan açıklamaları içerir.
kod bloğu: Fonksiyon gövdesini oluşturan bir veya daha fazla geçerli python ifadesine verilen isimdir.
return: Fonksiyondan bir değer döndürmek için isteğe bağlı olarak kullanılabilen bir dönüş ifadesidir.
Bir fonksiyon tanımladıktan sonra, fonksiyon başka bir fonksiyondan, programdan ve hatta Python komut isteminden çağrılabilir. Bir fonksiyonu çağırmak için, uygun parametrelerle birlikte fonksiyon adının yazılması yeterlidir. Ancak, Python’da, fonksiyon tanımı her zaman fonksiyon çağrısından önce bulunmalıdır. Aksi takdirde yorumlayıcı fonksiyon bulunamadı hatası verecektir.
return İfadesi
Return ifadesi, bir fonksiyondan çıkmak ve fonksiyonun çağrıldığı yere geri dönmek için kullanılır.
return Sözdizimi:
return [ifade listesi]
Bu ifade, değer hesaplayan veya değer döndürülen bir ifade içerebilir. Deyimde ifade yoksa veya bir fonksiyonun içinde return ifadesi bulunmuyorsa, fonksiyon None nesnesini döndürür.
Değişkenlerin Kapsamı ve Ömrü
Bir değişkenin kapsamı, bir programın değişkenin değer ataması yapılabildiği, yani yorumlayıcı tarafından tanındığı kısmıdır. Bir fonksiyon içinde tanımlanan parametreler ve değişkenler fonksiyonun dışından görünmez yani erişilemez. Bu nedenle, yerel bir kapsamları vardır.
Fonksiyonun dışındaki değişkenler fonksiyonun içinden erişilebilir. Yani küresel bir kapsamları vardır.
Bu değerler fonksiyonun içinden okunabilir ancak değiştirilemez. Fonksiyon dışındaki değişkenlerin değerini değiştirmek için, global anahtar sözcüğü kullanılarak global değişkenler olarak bildirilmeleri gerekmektedir.
Bir değişkenin ömrü, değişkenin tanındığı, bellekte bulunduğu süreye denir. Bir fonksiyon içindeki değişkenlerin ömrü, fonksiyonun yürütüldüğü süre kadardır. Fonksiyondan dönüldüğünde yok edilirler. Bu sebeple, bir fonksiyon daha önce yapılan çağrılarından bir değişkenin değerini tutamaz.
Fonksiyon Türleri
Kullanıcı Tanımlı Fonksiyonlar
Belirli bir görev için kullanıcı tarafından hazırlanmış fonksiyonlar, kullanıcı tanımlı fonksiyonlar olarak adlandırılır.
Python ile öntanımlı olarak gelen fonksiyonlara yerleşik, dahili fonksiyonlar denir. Kütüphane biçiminde başkaları tarafından yazılan fonksiyonlar ise, kütüphane fonksiyonları olarak adlandırılabilir.
Kullanıcı tanımlı fonksiyonların avantajları:
• programın anlaşılmasını, bakımını ve hata ayıklamasını kolaylaştırır. • Bir programda tekrarlanan kod oluşursa, bu kodlar bir fonksiyona dahil edilerek, ihtiyaç duyulan yerlerde bu fonksiyon çağrılabilir. • Farklı programcılar, farklı fonksiyonlar yaparak iş yükünü bölebilir.
Dahili (Built-in) Fonksiyonlar
Python dilinin kullanıma hazır çeşitli fonksiyonları vardır. Bu fonksiyonlara yerleşik, dahili, ön tanımlı fonksiyonlar denir. abs(), any(), chr(), hex(), input(), len(), open(), print() vb. fonksiyonlar dahili fonksiyonlara örnektir.
Fonksiyon Argümanları/Parametreleri
Python’da, farklı sayılarda argüman/parametre alabilen fonksiyonlar tanımlanabilir. Tanımlanan fonksiyonlar, belirtilen argümanlara uygun olarak çağrılmalıdır. Çağırırken fonksiyon (arguman1, argüman 2) kullanılır.
Değişken Sayıda Fonksiyon Argümanları
Şimdiye kadar, fonksiyonların aldığı sabit sayıda argüman kullanımı incelendi. Python’da değişken sayıda argüman alabilen bir fonksiyon tanımlamanın başka yolları da vardır. Bu tipin üç farklı kullanım şeklini inceleyelim.
Python Varsayılan Argümanlar
Python’da parametreler varsayılan değerlere sahip olabilir. Atama operatörü (=) kullanılarak bir argümana varsayılan bir değer sağlanabilir.
fonksiyon (arguman1, argüman 2= ..)
Bir fonksiyonda ihtiyaç duyulduğu kadar bağımsız değişken varsayılan bir değere sahip olabilir. Ancak bir tane varsayılan argüman olduğunda, sağındaki tüm argümanların da varsayılan değerlere sahip olması gerekmektedir. Bu, varsayılan olmayan argümanların varsayılan argümanları takip edemeyeceği anlamına gelir.
Python Anahtar Kelime Argümanları
Bazı değerlere sahip bir fonksiyon çağırdığımızda, bu değerler konumlarına göre argümanlara atanır.
Python, işlevlerin anahtar kelime argümanları kullanılarak çağrılmasına izin vermektedir. Fonksiyonlar bu şekilde çağrıldığında argümanların sırası (konumu) değiştirilebilir.
Bir fonksiyon çağrısı sırasında konumsal argümanlar anahtar kelime argümanları ile karışık bir şekilde çağrılabilir. Ancak anahtar kelime argümanlarının konumsal argümanları takip etmesi gerektiği unutulmamalıdır. Anahtar kelime argümanlarından sonra konumsal bir argüman çağırmak hatalara neden olacaktır.
Python İsteğe Bağlı Argümanlar
Bazen bir fonksiyona geçirilecek argüman sayısı önceden bilinmeyebilir. Python, bu tür durumları, isteğe bağlı sayıda argüman içeren fonksiyon çağrıları yoluyla ele alınmasını sağlar. Fonksiyon tanımında, bu tür bir argümanı belirtmek için parametre adından önce bir yıldız işareti (*) kullanılır. (def fonksiyon (*argüman)) Bu durumda, fonksiyon birden çok argümanla çağırılır. Bu argümanlar, fonksiyona aktarılmadan önce bir tupple’a (demet) aktarılır. Fonksiyonun içinde, tüm argümanları alabilmek için bir for döngüsü kullanılır.
Özyinelemeli Fonksiyonlar (Recursive)
Python’da bir fonksiyonun içerisinden diğer fonksiyonların çağrılabilmesinin yanında, fonksiyonun kendisini çağırması da mümkündür. Bu tür yapılar özyinelemeli fonksiyonlar olarak adlandırılır. Özyineleme, bir şeyi kendi içerisinde tanımlama sürecidir. Özyinelemeli fonksiyonlarda, sonsuz bir döngüye girmemesi için mutlaka fonksiyonun kendini çağırmasını durduracak bir kontrol eklenmelidir. Her özyinelemeli fonksiyonun özyinelemeyi durduran bir temel koşulu olmalıdır, aksi takdirde işlev kendini sonsuza kadar çağıracaktır.
Python yorumlayıcısı, yığın taşmalarına neden olan sonsuz yinelemelerden önüne geçmek amacıyla, yinelemenin derinliklerini sınırlar. Varsayılan olarak, maksimum
özyineleme derinliği 1000’dir. Sınır aşılırsa, RecursionError ile sonuçlanır.
Özyinelemenin Avantajları:
• kodun temiz ve düzenli görünmesini sağlar. • Karmaşık bir görev, basit alt problemlere bölünebilir. • İç içe geçmiş karmaşık döngüler kullanmaktansa, özyinelemeli fonksiyon kullanmak daha kolay bir çözümdür.
Özyinelemenin Dezavantajları:
• özyinelemenin mantığını takip etmek zor olabilir. • çok fazla bellek ve zaman harcadıkları için pahalıdır, verimsizdir. • hata ayıklamak zordur.
Lambda/Anonim Fonksiyonlar
Python dilinde anonim bir fonksiyon, isimsiz tanımlanmış bir fonksiyondur. Python’da normal işlevler def anahtar sözcüğü kullanılarak tanımlanırken, anonim işlevler lambda anahtar sözcüğü kullanılarak tanımlanır. Bu nedenle anonim işlevlere lambda işlevleri de denilmektedir.
Lambda fonksiyonun söz dizimi
lambda argümanlar: ifade
Lambda fonksiyonları herhangi bir sayıda bağımsız değişkene sahip olabilir, ancak yalnızca bir ifade olabilir. İfade değerlendirilir ve döndürülür. Lambda fonksiyonları, fonksiyon nesnelerinin gerekli olduğu her yerde kullanılabilir.
Kısa bir süre için isimsiz bir fonksiyona ihtiyaç duyduğumuzda lambda fonksiyonlarını kullanırız. Python’da bunu genellikle daha yüksek dereceli bir fonksiyonun argümanı olarak kullanırız. Lambda işlevleri, filter(), map() vb. gibi yerleşik fonksiyonlarla birlikte kullanılır.
filter() fonksiyonu
Python’daki filter() fonksiyonu, bir fonksiyonu ve bir listeyi argüman olarak alır. Fonksiyon, listedeki tüm öğelerle birlikte çağrılır ve fonksiyonun Doğru olarak değerlendirdiği öğeleri içeren yeni bir liste döndürür.
map() fonksiyonu
Python’daki map() fonksiyonu, bir fonksiyon ve bir liste alır. Fonksiyon, listedeki tüm öğelerle birlikte çağrılır ve her öğe için o fonksiyon tarafından döndürülen öğeleri içeren yeni bir liste döndürülür.
global, local ve nonlocal Anahtar Kelimeleri
Python programlama diline değişkenlerin program içindeki kapsamlarını bildiren anahtar kelimeler mevcuttur.
Global Değişkenler
Python’da, fonksiyonun dışında veya global kapsamda bildirilen bir değişken, global değişken olarak isim-
lendirilir. Bu, global bir değişkene fonksiyonun içinden veya dışından erişilebileceği anlamına gelmektedir.
Python’da, global değişkenleri tutmak ve aynı program içindeki Python modülleri arasında bilgi paylaşmak için bir config.py modülü oluşturulur.
Local (Yerel) Değişkenler
Fonksiyon gövdesinde veya yerel kapsamda bildirilen bir değişken yerel değişken olarak adlandırılır.
Nonlocal (Yerel Olmayan) Değişkenler
Yerel kapsamı tanımlanmamış iç içe fonksiyonlarda yerel olmayan değişkenler kullanılır. Bu, değişkenin ne yerel ne de global kapsamda olamayacağı anlamına gelir. Yerel olmayan değişkenler oluşturmak için nonlocal anahtar kelimesi kullanılmaktadır. Yerel olmayan (nonlocal) olarak tanımlanmış bir değişkenin değeri değiştirildiğinde, değişiklikler yerel (local) değişkende de görünür.
Modül Yapısı (Module)
Modül, python koduna sahip bir dosyadır; bir kod kütüphanesidir. Uygulamada kullanılacak fonksiyonları içerir. Kod, değişkenler, işlevler veya tanımlanmış sınıf biçiminde olabilir. Dosya adı modül adı olarak kullanılır.
Büyük programları küçük yönetilebilir ve düzenlenmiş dosyalara bölmek için modüller kullanılmaktadır. Ayrıca, modüller kodun yeniden kullanılabilirliğini sağlamaktadır. İçeriklerini farklı programlara kopyalamak yerine en çok kullanılan fonksiyonlar bir modül içerisinde tanımlanabilir. Modüller import anahtar kelimesi ile koda dahil edilirler.
import Anahtar Kelimesi
Bir modülün içindeki tanımlar, başka bir modüle veya Python’daki etkileşimli yorumlayıcıya aktarılabilir. Bunu yapmak için import anahtar sözcüğü kullanılmaktadır.
Modül adından sonra nokta işareti kullanarak fonksiyona erişilebilir.
Python dilinin çok sayıda standart modülü vardır. Bu dosyalar, Python’ın kurulduğu konumun içindeki “lib” dizinindedir. Standart modüller de kullanıcı tanımlı modüllerimizi içe aktardığımız gibi içe aktarılarak kullanılabilir. Modülleri içe aktarmanın çeşitli yolları vardır.
Python import İfadesi
Pyhton’da hazırlanmış bir modül, import deyimi kullanılarak içe aktarılabilir ve nokta operatörü kullanılarak içindeki tanımlara erişilebilir.
Yeniden Adlandırarak İçe Aktarma
Python’da bir modül, farklı bir isimlendirme ile programa aktarılabilir. Kod içerisinden de yeni verilen isim üzerinden “.” operatörü vasıtasıyla içerdiği fonksiyonlara erişilebilir. Artık yapılacak tüm işlemler, modülün yeni adı üzerinden yapılmalıdır. Eski modül adının bir geçerliliği yoktur.
Yeniden isimlendirilen bir modüle artık eski ismi ile bir çağrı yapılamaz. Yeni ismi üzerinden işlemler gerçekleştirilmelidir.
Python from …import… İfadesi
Python dilinde, modülü bir bütün olarak içe aktarmadan sadece ihtiyaç duyulan belirli fonksiyonları içe aktarabiliriz. (from modül import fonksiyon)
Tüm Tanımlamaların İçe Aktarımı
Aşağıdaki yapıyı kullanarak tüm adları (tanımları/fonksiyonları) bir modülden içe aktarabiliriz. (from modül import *). Ancak yıldız (*) sembolü ile her şeyi içe aktarmak iyi bir programlama uygulaması olarak görülmez. Yinelenen tanımlara yol açabileceği gibi, kodun okunabilirliğini de engeller.
Yeniden Yükleme (Reload) İşlevi
Python yorumlayıcısı, bir oturum sırasında bir modülü yalnızca bir kez içe aktarır. Böylece kodlar tekrar dahil edilmediği için, yorumlama işlemleri daha verimli hale gelmektedir.
Hazırlanan modül, program sırasında değiştiyse, modülün tekrar yüklenmesi gerekecektir. Bunu yapmanın bir yolu yorumlayıcıyı yeniden başlatmaktır. Ancak bu yöntem çok kullanışlı değildir. Python bunu yapmanın daha verimli bir yolunu sunmaktadır. Bir modülü yeniden yüklemek için imp modülünün içindeki reload() işlevi kullanılabilir.
Paket Yapısı (Package)
Bilgisayar ortamında, benzer nesneler daha hızlı erişim ve kategorizasyon için genellikle aynı isimli klasör yapıları içerisinde saklanır. Python programlama dilinde de bir dizin yapısı altında toplanmış, birbiri ile bağlantılı, alakalı modüllere paket adı verilmektedir. Dolayısıyla, paket modüllerden oluşan bir yapıdır.
Hazırladığımız program çok sayıda modülle büyüdüğü için benzer modülleri bir pakete, farklı modülleri farklı paketlere yerleştiririz. Bu, bir projeyi (programı) yönetmeyi kolay ve kavramsal olarak net hale getirecektir.
Benzer şekilde, bir dizin alt dizinleri ve dosyaları içerebileceğinden, bir Python paketinin alt paketleri ve modülleri olabilir. Python’un bir yapıyı paket olarak kabul etmesi için, __init__.py adlı bir dosya içermelidir. Bu dosya boş bırakılabilir, ancak genellikle o paketin başlatma kodu bu dosyaya yerleştirilir.
Modülü Bir Paketten İçe Aktarma
Nokta (.) operatörü kullanılarak paketlerden modüller içe aktarılır.
Python, paketleri içe aktarırken, modül arama yoluna benzer şekilde sys.path içinde tanımlanan dizinler listesini kontrol eder.
Paket Yöneticisi (PIP)
Python dilinde uygulama geliştirenler, kendi hazırladıkları paketleri diğer kullanıcılarının da erişimine açabilmektedir. Bu paylaşılan Python paketlerinin yüklenebilmesi amacıyla ortak bir yükleyici oluşturulmuştur. Bu paket yükleme ortamına “pip” adı verilmektedir. Pip’in “Pip installs
Python” ya da “Pip installs packages” şeklinde açılımları mevcuttur.
Pip, PyPI (The Python Package Index) ortamındaki paketlerin kurulması, güncellenmesi veya kaldırılmasını sağlamaktadır. https://pip.pypa.io/ adresinden kurulum kodunun çalıştırılması gerekmektedir.
Python ortamınızda pip kurulu değilse, pip’in kurulumu için doğrudan pip’in sağlayıcıları tarafından desteklenen 2 mekanizma vardır: ensurepip ve get-pip.py
ensurepip
Python, bir Python ortamına pip yükleyebilen bir “ensurepip” modülü ile birlikte gelmektedir.
Linux ortamında: $ python -m ensurepip --upgrade
MacOS ortamında: $ python -m ensurepip --upgrade
Windows ortamında: C:\> py -m ensurepip --upgrade
get-pip.py
Bu Python betiği, pip yüklemek için bir takım önyükleme mantığı kullanmaktadır. “get-pip.py” komut dosyasının https://bootstrap.pypa.io/get-pip.py adresinden indirilmesi gerekmektedir. Bir terminal/komut istemi yardımıyla, get- pip.py dosyasını içeren klasöre cd komutu ile girdikten sonra, kullanılan işletim sistemine uygun komutlar çalıştırılarak kurulum yapılır.
Linux ortamında: $ python get-pip.py
MacOS ortamında: $ python get-pip.py
Windows ortamında: C:\> py get-pip.py
Pip kurulumu için işletim sistemine uygun komutlar çalıştırıldıktan sonra, Python paket yükleyicisi sisteminize doğru bir şekilde yüklenmiş olacaktır.
pip --version ya da pip --help
Kurulumun başarılı olarak yüklendiğini kontrol etmek için bu komutlar çalıştırılabilir. Eğer ekranda “pip: command not found” uyarısı alıyorsanız, paket yükleyicisi yüklenmemiştir ve tekrar yüklemeyi denemelisiniz.
Modüller ve fonksiyonlarda olduğu gibi paketlerin de türleri vardır. Paketler, kaynaklarına göre iki gruba ayrılmaktadır: Standart Paketler ve Üçüncü Şahıs Paketleri
İsimlerinden paketlerin içerikleri anlaşılsa da, paket türlerine kısaca değinelim.
Standart Paketler
Bu paketler, Python kurulumu sırasında gelen, standart kütüphanesinde bulunan paketlere verilen isimdir. Bilgisa- yarda Python kurulum klasörü altında bulunan lib klasöründen erişilebilir. Bir paketin tam olarak nerede olduğu, ilgili paketin __path__ özelliği sorgulanarak öğrenilebilir. (>>> import urllib ve >>> urllib.__path__)
Sorgulanan nesne bir paket değilse, __path__ özelliği de olmayacaktır.
Python programlama dili çalıştırılması için yorumlayıcıya ihtiyaç duymaktadır ve yüksek seviyeli bir dildir.
Python dilinde modüllerin __path__ özelliği bulunmamaktadır.
Paketler için tanımlanmış bu özellik ile paketin hangi klasör yapısı altında bulunduğu verisini elde etmiştik. Bu klasöre, yani “urllib” paketi içerisine gittiğimizde karşımıza farklı dosyalar çıkacaktır.
Paketlerin modüllerden oluştuğundan bahsetmiştik. “urllib” paketi de bu modüllerden oluşmaktadır. Bu yapı sayesinde, hangi paketin hangi modüllerden oluştuğu görülebilir.
Üçüncü Şahıs Paketleri
Bu paketler, Python geliştiricileri dışında hazırlanmış ve kullanıcıların hizmetine sunulmuş araçlardır. Bu paketler, standart paketler gibi gelmediğinden, kullanabilmek için kurulumlarının yapılması gerekmektedir.
https://pypi.org adresinde 60 binden fazla, kullanıcılar tarafından hazırlanarak erişime açılmış paket mevcuttur. Bu adresten kurulmak istenen paket adı öğrenilerek, kurulum komutu ile kurulum tamamlanabilir.
pip3 install paket_adı
Bilgisayarımıza django paketinin kurulumunu yapmak istediğimizde, https://pypi.org/project/Django/#files adresinden paketin son sürümü indirmekle işe başlayabiliriz. İndirilen tar.gz uzantılı sıkıştırılmış dosya açıldığında pek çok klasör ve dosya çıkacaktır. Django klasörünün içerisine girildiğinde setup.py isimli bir kurulum dosyası görülecektir. Pip komutu yerine bu dosya çalıştırılarak paket kurulumu yapılabilir. Kurulum dosyasını çalıştırmak için de şu komut çalıştırılmalıdır:
python3 setup.py install
Burada dikkat edilmesi gereken önemli bir nokta da, hangi Python sürümü ile kurulmuşsa, ilgili paket sadece o sürüm ile çalışacaktır. Ayrıca paketin kurulumunu yapabilmek için install parametresi de ilave edilmesi gerekmektedir.
Paket Oluşturma
Python dilinde ihtiyaca uygun paketlerin kullanılmasının yanında, kendi hazırladığınız kodları başkalarının da kullanımına açabilirsiniz. Paket oluşturmak için, Python kodlarını içeren .py uzantılı dosyaları bir klasör altında toplanması yeterlidir. Böylece klasör adını taşıyan bir paket elde edilecektir.
Paket klasörünü içeri aktardıktan sonra eklediğimiz klasörün gerçekten bir paket olup olmadığını __ path__ ve __package__ niteliklerini kullanarak test edebiliriz. __path__ niteliği sadece paketlerde mevcuttur. __package__ niteliği de eğer bir pakette test edilirse paket ismini, bir modülde test edilirse de boş bir metin döndürecektir.