Ders 6
1.16 - Python Programlarının Oluşturulması
Python programları, *.py dosyaları halinde diskte saklanır. Python2x programlarından *.exe dosyaları yapılması olanağı üçüncü parti programları ile gerçekleştirilebilirken, Python3x programları için henüz bu olanak sağlanamamıştır. Python programlarının yazımı ve çalıştırılması için, başta ECLIPSE olmak üzere birçok IDE 'den yararlanılabilir. Bu konuda, Python-kurulumu.html sayfasında bilgi verilmiştir. Daha yeni bir tümlenmiş geliştirme ortamı (Integrated Development Environment = IDE) Pyton notebook'larıdır. Notebook lar defter olarak düşünülmemelidir. Bu Matematica'da başlatılmış bir hücresel yazılım ve derleme yöntemidir. Python notebook ları, IPython geliştirme ortamı olarak da adlandırılmaktadır. IPython notebook'ları, Anaconda ve WinPtython aglomeratlarında çalıştırlabilir. En gelişmiş IPython ortamı, Jupiter notebookları olarak adlandırılır ve WinPython sisteminde çalıştırılabilir. Bir WinPython aglomaratı, Jupiter notebook'ları yanında, çok kullanışlı bir tümlenmiş geliştirme ortamı olan Spyder ortamını da içermektedir.
1.16.1 - Kodlama Dili
Python programlarının ilk satırında, program yazımın karakter kodlaması belirtilebilir. Program kodlamasındaki kodlama dili Python derleyicisinin tanıdığı dillerden birisi olmalı ve kodlama yorum satırı, sadece bu amaçla yazılmış bir yorum satırı olmalıdır. Python 3 , orijinal olarak UTF-8 kodlamasını kullanır. Bu nedenle, UTF-8 kodlaması için özel bir bildirim yapılması gerekli değildir. Türkçe tanıtıcı isimler kullanılması halinde UTF-8 kodlaması kullanılabileceğinden, hiçbir kodlama bildirimi yapmaya gerek olmamaktadır. Kodlama bildirimi,
# -*- coding: <encoding name> -*-
şeklindedir.
UTF-8 kodlaması altında Türkçe tanıtıcıların kullanılmasının bazı hatalara neden olduğu bildirilmiştir. Bu hatalara rastlanması küçük bir olasılık dahi olsa, yine de bir önlem olarak Türkçe tanıcılar kullanılmamalıdır. Bir başka sorun da, Python derleyicisinin ASCII karakterler dışındaki karakterler için unicode modülünde karakterin geçerli olup olmadığının araştırması ile yaşanacak zaman kaybıdır. Bu nedenlerle, UTF-8 altında çalışılmalı fakat, eğitim çalışmaları dışında Türkçe tanıtıcıların kullanımı en aza indirilmelidir. İleride, Türkçe Python derleyicilerinin yazılması en iyi çözüm olacaktır
1.16.2 - Modüler Yapı
Modüler yapı, Python programlama dilinin üstün noktalarından biridir. Python programları önceden hazırlanmış isim alanları altında çalışırlar. Her program, başlangıçta builtinsadında bir temel modül altında başlar. Bu modül, varsayılan modüldür ve hçbir bildirime gerek olmadan programa otomatik olarak import edilir.
Programa varsayılan olarak ithal edilmiş olan builtins modülü programın varsayılan olarak bu modülün isim alanında çalışmasını belirler. Bu modül programda gerek duyulacak birçok özelliği içerir. Bu modülün değer özellikleri ve fonksiyon özellikleri her Python programında erişilebilir niteliktedir.
Varsayılan olarak builtins modülü alında çalışmakta olan her Python programında, yeni bir değişken deklare etmek, builtins modülüne yeni bir özellik eklemekle eşdeğerdir. Örnek olarak bir Python programında a = 1 şeklinde yeni bir değişken tanımlanması, prensip olarak builtins.a = 1 şeklinde builtins modülünde yeni bir değer özelliği tanımlanması ile eşdeğerdir. Buna rağmen, builtins modülü, varsayılan modül olduğundan, bu modül isim alanındaki özellklerin kalifiye ismine builtins eklenmsi gerekmez. Yani, porgramınızda yeni bir a değişkeni tanımlamışsanız bunu program içinde yine a olarak çağırabilirsiniz. Bu tüm builtins modülünde varsayılan olarak bulunan değer özellikleri ve metotlar için de geçerlidir. Yani hiçbirinin kalifiye ismine builtins. eklenmesi gerekmez.
Python programlarının doğrudan doğruya builtins isim alanında çalışmaları, programcıya bazı yükümlüklükler getirir. Prensip olarak, builtins isim alanında tanımlı değer özellikleri ve modüller, programlama alanında varsayılan sabitler ve hazır fonksiyonlar işlevini yaparlar. Programcılar bu öntanımlı sabit ve fonsiyonların tanıtıcıları ile aynı tanıtıcıları kullanarak yeni değişken ve fonksiyonlar tanımlarsa, bunlar varsayılan sabitler ve foksiyonlarla bir isim çakışması (name clash) yaratırlar ve eski sabit veya fonksiyonları yeniden tanımlayarak eski tanımlarının üstüne çıkarlar (overriding). Bu durumda programlar istendiği gibi çalışmaz. Bu konuda dikkatli olunmalı, builtins modülünün içeriği iyi incelenerek isim çakışmalarına olanak verilmemelidir.
bool | enumerate | map | set | type |
bytearray | filter | memoryview | slice | zip |
bytes | float | object | staticmethod | |
classmethod | frozenset | property | str | |
complex | int | range | super | |
dict | list | reversed | tuple |
abs | dir | help | max | round |
all | divmod | hex | min | setattr |
any | eval | id | next | sorted |
ascii | exec | input | oct | sum |
bin | format | isinstance | open | vars |
callable | getattr | issubclass | ord | |
chr | globals | iter | pow | |
compile | hasattr | len | ||
delattr | hash | locals | repr |
Python programlarında varsayılan modül olan builtins modülü, birçok kullanışlı özellik içermesine karşın hiçbir zaman her program projesinin gereksinmelerini karşılayamaz. Her program projesinin hedefleri farklıdır, gereksinmeleri farklıdır. Her program projesi, bulunabildiği ölçüde eski alt programlardan yararlanır. Hedeflerine ulaşmasını sağlayabilecek eskiden yapılmış olan alt programların bulunamadığı durumlarda, gerekli program kodları proje içinde geliştirilir. Bu durumda, herkadar kullanılabilir eski alt program bulunabilirse, proje de o kadar hızlı ilerler. Dolayısı ile önceden geliştirilmiş olan alt programlar, proje çalışmaları için çok değerlidir. Python bu gereksinmeyi modül bazında çalışmalarla karşılamaya çalışmaktadır. Modüller, aslında Python derleyicisinin bulabileceği yerlere yerleştirilmiş dosyalardır. Python modülleri nesne yapısındadır. Modül kodları Python programlama dilinde veya derlenmiş C kodları ile yazılmış fonksiyon (metod) ve değerlerden oluşur.
Bir Python programında varsayılan modül olan builtins modülü dışında başka modül veya modüllerin kullanılması istendiğinde, ilkönce bu modüllerin program isim anaında erişilebilir olmasının sağlanması gerekir. Bu erşim ise, istenilen modülün program isim alanına ithal (import) edilmesi ile sağlanır.
Bir modülün, bir program isim alanına ithal (import) etmek için aşağıda belirtilen program adımları uygulanabilir:
import <modül adı>;
Bu tür bir erişim sağlanması en okunabilir kod sağlayan ve programlamada isim çakışmalarını engelleyen en sağlam erişim sağlama şeklidir. Bu yöntemle, sadece ithal edilen modülün isim alanına erişim sağlanabilir ve builtins modülü içindeki özelleikler öneksiz, ithal edilen modülün isim alanına ise, modül ismi öneki ile erişilir. Bu şekilde, builtins modülü ile ithel edilen modül isim alanları birbirinden ayrı tutulur ve isim çakışması olasılığı azaltılmış olur. Örnek olarak, bir Python programının çalıştığı IDE nin modül arama yolu, sys modülünün path değer özelliğindedir. Bunu bir IDE'nin örnek olarak ECLİPSE ide sinin interaktif konsolunu kullanarak saptayalım:
>>>import sys ; >>>sys.path; >>>Out[3]:
['J:\\eclipse-standard-luna-R-win32-x86_64\\eclipse\\plugins\\org.python.pydev_3.6.0.201406232321\\pysrc',
'C:\\Python34\\lib\\site-packages\\ipython-3.0.0_dev-py3.4.egg',
'C:\\Python34\\DLLs',
'C:\\Python34\\lib',
'C:\\Python34',
'C:\\Python34\\lib\\site-packages',
Buradan eğer bir modül yazarsak nereye kaydetmemiz gerektiğini bulabiliyoruz. Artık kendi modülümüzü yazıp import edebiliriz. Kullandığımız bir IDE yi açıp aşağıdaki fonksiyonu yazıyoruz:
def alan(x , y): s = str(x * y); s = 'Bu karenin alanı :\t' + s + '\tbirimdir.'; return s;
Bu programı, satır satır açıklayalım. İlk olarak alan bir fonksiyon tanıtıcısı, tanıttığı fonksiyonun x ve y olarak iki formal parametresi var. Bu fonsiyonun içeriği,
s = str(x * y);
satırı bir tek ifadeden oluşmaktadır. Bu ifadede en düşük işlemci, atama işlemcisi olan = dir. Bundan dolayı ilk olarak en yüksek öncelikli işlemci olan * işlemcisinin işlemi gerçekleştiriliyır. Oluşan sonuç builtins modülünün str() sayısal verileri sözel tipe dönüştürme fonksiyonu ile sözel tipe dönüştürülüyor. En sonunsa, sağ işlenenin oluşan sonucu, sol işlenen olan s tanıtıcısı ile erişim sağlanabilen bir bellek alanına yerleştiriliyor. Bundan sonraki program adımı,
s = 'Bu karenin alanı :\t' + s + '\tbirimdir.';
şeklinde bir ifadedir. Bu ifadede en düşük öncelikli işlemci, atama işlemcisi = dir. Bu işlemcinin öncelikle sağ işleneninin çözümlenmesi yapılacak ve oluşan değer sol işlemcinin belirttiği bellek alanına yerleştirilecektir. Sağ işlenende ise iki tane eşit öncelikli + işlemcisi bulunmaktadır. Burada öncelik sırası soldan sağadır. Yani ilk olarak, Bu karenin alanı : \t' + s işlemi yapılacaktır. Bu işlem bir sözel veri birleştirilmesidir. İlk veri bir sözel literal, ikinci veri, s tanıtıcısının belirttiği bellek adresinde saklı olan güncel, sözele dönüştürülmüş sayısal veridir. Bu işlem sonucunda iki sözel veri birleştirlir. Sonra ikinci birleştirme işlemi de yapılarak tek bir sözel veri oluşturulur ve bu sözel veri yine s tanıtıcısının erişim sağladığı bellek alanına eski veri silinerek yerleştiriliyor. Bilindiği gibi, bu tahrip edici bir işlemdir.
En sonunda,
return s;
bildirimi ile, s tanıtıcısının işaret ettiği bellek alanında bulunan güncel değerin döndürüleceği bildirilerek fonksiyon tanımı tamamlanıyor.
Bu programı, yukarıdaki path bilgisinin belirttiği bir klasöre örnek olarak c:\python34\site-packages\bedriemir.py olarak yazıyoruz. Sonra yine IDE 'ye geçip aşağıdaki programı yazıyoruz:
import bedriemir
a = bedriemir.alan(25,100) print (a)
Bu programın sonucu:
Bu karenin alanı : 2500 birimdir.
Bu programda ilk olarak bedriemir modülünün program isim alanına ek bir isim alanı erişimi olarak import edilmesi yapılıyor. Daha önce bedriemir.py programı Python derleyicisinin aradığı klasörlerin birinde yerleştirilmiş olduğu için bulunması garantidir. Burada,
a = bedriemir.alan(25,100);
program adımı bir ifadedir. Bu ifadede en düşük öncelikli işlemci, atama işlemcisi = dir. Bu işlemcinin öncelikle sağ işleneninin çözümlenmesi yapılacak ve oluşan değer sol işlemcinin belirttiği bellek alanına yerleştirilecektir. Sağ işlenende ise bir fonksiyon çağrısı yapılmaktadır. Bu fonksiyon imğpoert edilen bedriemir modülünün bir fonksiyonudur ve çağrının yapıldığı fonksiyonun kalifiye isminde, önce fonksiyonun tanımlanmış olduğu ve programın da erişim sağlayabildiği (import ederek) modülün ismi, sonra da fonksiyonun ismi bulunmaktadır. Bu fonksiyon gerektirdiği gibi, iki sayısal argüman ile çarılmaltra ve geri döndürülen değer, a tanıtıcısın erişim sağladığı bellek alanına yerleştirilmektedir.
En son,
print (a);
program adımı, a tanıtıcısının erişim sağladığı bellek alanındaki güncel değerin standart çıktı cihazında (burada monitördür) görüntülenmesini sağlayan öntanımlı print() fonksiyonudur. Bu fonksiyonun çalışmasını ileride daha detaylı olarak inceleyeceğiz. Bu fonksiyon her türlü sözel veriyi doğrudan, sayısal veriyi de otomatik olarak, sözele çevirerek görüntüleyebilir. Sonuçta print() fonsiyonu görüntülenen program sonucu eğer alan(x,y) fonksiyonun cağrılmasında kullanılan x ve y argümanları aynı birimden iseler, görüntülenen alan birimi, her iki uzunluğun belirtildiği birim sisteminin alan birimindedir.
Bu arada kutlarız, ilk programınızı gerçekleştirdiniz. İlk programı gerçekleştirmekten başka üstelik ilk modülünüzü de yazdınız. Bu programı yazacak bilgimiz oluşmuş olduğuna göre artık her türlü Python programını yazabiliriz.
Bir modülün global isim alanına (program alanına) ithal etmek için, bir başka yol,
import <modül adı>* veya eşdeğer olarak, from <modül adı> import*
şeklindedir. Bu yolla program isim alanına (global isim alanına) ithal edilen bir modülün bütün özellikleri global isim alanına akar ve tüm özellikleri, modül adı verilmesine gerek olmadan yani kalifiye isimlerine gerek olmadan erişilebilir. Bunun yanıda her türlü isim çakışması olasılığı da beraber gelir. Global isim alanı, zaten builtins modülünün otomatik ithal edilmesi dolayısı ile builtins + program içi ortak isim alanıdır. Buraya gelişigüzel isim doldurulması doğru değildir. Bu kadar isim programın hızını azaltır, ayrıca hemen yaratmasa da potansiyel bir isim çakışması kaynağını oluşturur. Erişilen fonksiyonlar da, modül ismine gerek olmadan erişilebildiğinden, hangi fonksiyonun hangi modülden geldiğinin anlaşılması da uzun inceleme gerektirir. En iyisi bu tür ithal işleminden tümüyle vazgeçmektir. Yine de, bu çalışma dahil birçok çalışmada bu kolay yolun kullanıldığı görülebilir. Bunun nedeni, kalifiye isim kullanımı gerekli olmadığından, daha az klavye kullanımı ile yazılım yapılabilmesidir. Buna bir noktada, insanların kolaya kaçma eğiliminin bir göstergesi olarak da bakılması gerekir.
Bir başka yöntem,
from <modül adı> import fonksiyon1 , fonksiyon2 , ...
şeklindedir. Bu en iyi modül ithal etme şeklidir. Fakat, hangi modülden hangi fonksiyonun ithal edileceğinin önceden iyi incelenmiş olması gerekir. Ne yazık ki programcılar bu kadar çalışkan olmuyorlar.
Bu kısımda modüllerin ana programa nasıl edileceğini inceledik, bu arada global ve moüdül ve yerel (kendi yarattığımız nesnelerin içi) isim alanlarını da tanımış olduk. Bir sonraki kisimda program giriş-çıkış ve sonuçların biçimlendirilmesi (formatlanmması) üzerinde duracağız.