4. Akış Denetimi
- 4.1.
if
Deyimi - 4.2.
for
Deyimi - 4.3.
range()
işlevi - 4.4. Döngülerde
break
,continue
veelse
Deyimleri - 4.5.
pass
Deyimi - 4.6. İşlev Tanımlama
- 4.7. İşlev Tanımları Üzerine Daha Fazla Bilgi
Bir önceki bölümde tanıtılan while
deyiminin yanısıra
Python'da diğer yazılımlama dillerinde de bulunan genel akış denetim
deyimleri (bazı farklarla birlikte) vardır.
4.1. if
Deyimi
Belki de en iyi bilinen deyim türü if
deyimidir. Örnek:
>>>
x = int(raw_input("Lütfen bir sayı girin: "))>>>
if x < 0:...
x = 0...
print 'Negatif sayı sıfırlandı'...
elif x == 0:...
print 'Sıfır'...
elif x == 1:...
print 'Bir'...
else:...
print 'Birden büyük'...
Sıfır veya daha fazla elif
deyimi olabilir, ve
else
deyimi seçimliktir. elif
deyimi else if
deyiminin kısaltılmışıdır ve aşırı
girintileri engellemesi açısından faydalıdır. Bir if ... elif
... elif ...
deyimleri dizisi diğer dillerde bulunan
switch
veya case
deyimlerinin
yerine kullanılabilir.
4.2. for
Deyimi
for
deyimi Pascal veya C dillerinde görülenden biraz
farklıdır. Python'daki for
deyimi herhangi bir sıranın
(liste, dizge, vs.) elemanları üzerinde sırayla yinelenir. Örnek:
>>>
# Bazı dizgelerin boylarını ölçelim:...
a = ['kedi', 'pencere', 'kertenkele']>>>
for x in a:...
print x, len(x)...
kedi 4 pencere 7 kertenkele 10
Üzerinde yinelenilen sırada değişiklik yapmak güvenli değildir (bu sadece listelerde olabilir). Eğer böyle bir şey yapacaksanız bu iş için dilim gösterimi ile listenin bir kopyasını kullanabilirsiniz:
>>>
for x in a[:]: # tüm listenin bir kopyasını oluştur...
if len(x) > 8: a.insert(0, x)...
>>>
a ['kertenkele', 'kedi', 'pencere', 'kertenkele']
4.3. range()
işlevi
Eğer bir sayı sırası üzerinde tekrarlamalar yapmak isterseniz, belirli
bir sıraya göre üretilen sayılardan oluşan bir liste oluşturan
range()
yerleşik işlevini kullanabilirsiniz.
Örnek:
>>>
range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Verilen bitiş noktası asla üretilen listenin bir parçası olmaz;
range(10)
ifadesi 10 elemanı olan bir liste oluşturur.
Listenin başlayacağı sayıyı ve artış miktarını da belirlemek mümkündür.
Artış miktarı negatif de olabilir.
>>>
range(5, 10) [5, 6, 7, 8, 9]>>>
range(0, 10, 3) [0, 3, 6, 9]>>>
range(-10, -100, -30) [-10, -40, -70]
range()
ve len()
işlevlerini bir
arada kullanarak da bir listenin elemanları üzerinde döngüler
kurabilirsiniz:
>>>
a = ['Python', 'yazılımlama', 'öğrenmek', 'çok', 'kolay !']>>>
for i in range(len(a)):...
print i, a[i]...
0 Python 1 yazılımlama 2 öğrenmek 3 çok 4 kolay
4.4. Döngülerde break
, continue
ve else
Deyimleri
break
deyimi, C'de olduğu gibi, içinde kaldığı en küçük
for
veya while
döngüsünden
çıkılmasına ve döngü deyiminin tamamen sona ermesine neden olur.
continue
deyimi döngü içindeki diğer deyimlerin
atlanıp bir sonraki yineleme işleminin başlamasına sebep olur.
Döngülerde else
ifadesi de kullanılabilir;
else
bloğu döngü bittiğinde (for
için) veya devamlılık koşulu geçersiz olduğunda (while
için) işletilir; fakat döngü break
deyimi ile sona
erdiyse işletilmez. Bunu asal sayılar bulan aşağıdaki örnekte görebilirsiniz:
>>>
for n in range(2, 10):...
for x in range(2, n):...
if n % x == 0:...
print n, 'asal sayı değil. çarpanlar:', x, '*', n/x...
break...
else:...
# çarpan bulunmadan döngü biter ise...
print n, 'asal sayıdır'...
2 asal sayıdır 3 asal sayıdır 4 asal sayı değil. çarpanlar: 2 * 2 5 asal sayıdır 6 asal sayı değil. çarpanlar: 2 * 3 7 asal sayıdır 8 asal sayı değil. çarpanlar: 2 * 4 9 asal sayı değil. çarpanlar: 3 * 3
4.5. pass
Deyimi
pass
deyimi hiçbir şey yapmaz. Python sözdizim
kurallarına göre bir ifadenin gerekli olduğu, fakat yazılımın bir
şey yapması gerekmediği zaman kullanılabilir:
>>>
while 1:...
pass # klavyeden CTRL+C ile kesilene kadar sürer...
4.6. İşlev Tanımlama
Herhangi bir değere kadar Fibonacci serisi yazan bir işlev yazalım:
>>>
def fib(n): # n'e kadar Fibonacci serisini yazdır...
"n'e kadar Fibonacci serisini yazdır"...
a, b = 0, 1...
while b < n:...
print b,...
a, b = b, a+b...
>>>
# Tanımladığımız işlevi çağıralım:...
fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
def
anahtar kelimesi bir işlev tanımını başlatır.
Bu deyimden sonra bir işlev adı ve parantez içinde bağımsız değişkenler yazılır.
İşlevin gövdesini oluşturan yazılım satırları sonraki satırdan itibaren
girintili olarak yazılır. İşlev gövdesinin ilk satırı bir dizge de
olabilir; bu dizge işlevin belgelenmesinde kullanılır (docstring).
İşlevlerin belgelenmesinde kullanılan dizgeleri (docstring) otomatik olarak çevrim içi ya da basılı belgeler oluşturmak için kullanan yazılımlar vardır. Ayrıca bazı geliştirme ortamları bunları yazılım yazarken kolaylık sağlaması için etkileşimli olarak yazılımcıya sunar. Yazdığınız işlevlere bunları eklemeyi bir alışkanlık haline getirmeniz faydalı olur.
Bir işlevin çağrılması (çalıştırılması) bu işlevdeki yerel değişkenlerin
olduğu bir simge tablosu oluşturur. İşlev içerisinde bütün değer atama
işlemlerinde değerler yerel simge tablosuna kaydedilir. Bir değişkene
başvuru durumunda ise önce yerel (local), sonra genel (global) ve en son
yerleşik (built-in) simge tablosunda arama yapılır. Bu yüzden genel
değişkenlere doğrudan değer atama yapılamaz (eğer
global
ifadesi içinde kullanılmamışlar ise); ancak
bunlara başvuru yapılabilir (reference).
İşlev çağırıldığında işlevin bağımsız değişkenleri yerel simge tablosuna eklenir; yani bağımsız değişkenler işleve değeri ile çağrı (call by value) kullanılarak iletilir (yani bağımsız değişkene yapılan değişiklikler yereldir, çağıran işlevdeki bağımsız değişkenlerde bir değişme olmaz).[68]
Bir işlev başka bir işlevi çağırdığında bu çağrı için yeni bir yerel simge tablosu oluşturulur.
Bir işlev tanımı işlev adının yürürlükte olan simge tablosuna eklenmesine sebep olur. İşlevin adı yorurumlayıcı tarafından kullanıcı tanımlı işlev veri türü olarak tanınır. Bu değer başka bir isime atanabilir ve bu da bir işlev olarak kullanılabilir. Bu genel bir isim değiştirme yolu olabilir:
>>>
fib <function object at 10042ed0>>>>
f = fib # f de fib işlevi olur>>>
f(100) 1 1 2 3 5 8 13 21 34 55 89
fib
'in bir işlev olmayıp bir yordam (procedure)
olduğunu düşünebilirsiniz. Python'da yordamlar, çağıran işleve
değer geri döndürmeyen işlevlerdir. Aslında yordamlar da bir değer
geri döndürürler, ama bu sıkıcı bir konudur. Bu değere
None
denir ve yerleşik bir değişkendir.
Yorumlayıcı yazılacak tek değer bu ise normalde None
yazmaz. Bunu görmeyi çok istiyorsanız şunu deneyin:
>>>
print fib(0)
None
Fibonacci serisini yazdırmak yerine, bunu bir liste şeklinde geri döndüren işlev yazmak basittir:
>>>
def fib2(n): # n e kadar fibonacci serisi geri döndürür...
" n e kadar fibonacci serisi içeren liste geri döndürür"...
sonuc = []...
a, b = 0, 1...
while b < n:...
sonuc.append(b) # değeri listeye ekle...
a, b = b, a+b...
return sonuc...
>>>
f100 = fib2(100) # işlevi çağır>>>
f100 # sonucu yazdır [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Bu örnekte de bazı yeni Python özelliklerini görüyoruz:
-
return
deyimi bir işlevden değer geri döndürür. Bağımsız değişkeni olmayan birreturn
deyimiNone
geri döndürür. Sona eren bir yordam (procedure) daNone
geri döndürür. -
sonuc.append(b)
ifadesi sonuç liste nesnesinin bir yöntemini çağırmaktadır. Bir yöntem bir nesneye `ait olan' venesne.yöntemAdı
şeklinde adlandırılan bir işlevdir.nesne.yöntemAdı
ifadesinde nesne herhangi bir nesne (bir ifade de olabilir) veyöntemAdı
da nesnenin türüne bağlı bir yöntemdir. Farklı veri türleri farklı yöntemlere sahiptir. Farklı veri türlerinin ayni isimli yöntemleri olabilir. Sonraki bölümlerde anlatılacağı gibi, kendi veri türlerinizi ve yöntemlerinizi oluşturmanız mümkündür. Yukarıdaki örnekte görülenappend()
yöntemi liste nesneleri için tanımlıdır ve bir listenin sonuna yeni elemanlar ekler. Bu örnekte busonuc = sonuc + [b]
ifadesinin yaptığını yapar; ancak daha verimlidir.
4.7. İşlev Tanımları Üzerine Daha Fazla Bilgi
Değişken sayıda bağımsız değişken alan işlevler tanımlamak da mümkündür. Bunun için kullanılan üç yöntem olup bunlar birleştirilerek kullanılabilir.
4.7.1. Bağımsız Değişken Değerlerini Önceden Belirleme
İşlev bağımsız değişkenlerine öntanımlı değerler atamak da mümkündür. Böylece çağıran işlev bu bağımsız değişkenleri sağlamazsa bunlar önceden belirlenmiş öntanımlı değerlerini alır. Örnek:
def onay_al(prompt, denemeler=4, sikayet='Evet veya hayır, lütfen !'): while True: ok = raw_input(prompt) if ok in ('e', 'evet'): return 1 if ok in ('h', 'hayır'): return 0 denemeler = denemeler - 1 if denemeler < 0: raise IOError, 'kararsız kullanıcı' print sikayet
Bu işlev onay_al('Programdan çıkmak istiyor musunuz?')
ya da onay_al('Dosyayı silmek istiyor musunuz?', 2)
şeklinde çağırılabilir.
İşlevin öntanımlı bağımsız değişkenleri işlevin tanımlandığı anda, o an yürürlükte olan etki alanı içinde değerlendirilir. Yani:
i = 7 def f(arg = i): print arg i = 6 f() 7
Uyarı
İşlevin öntanımlı bağımsız değişkenleri sadece bir defa değerlendirilir. Bu durum bağımsız değişkenin liste gibi değiştirilebilir bir nesne olduğu durumlarda farklılık yaratır. Örneğin aşağıdaki işlev ardarda çağırıldığında bağımsız değişkenlerinin değerlerini biriktirir:
def f(a, L = []): L.append(a) return L print f(1) print f(2) print f(3)
Bu şu çıktıyı verir:
[1] [1, 2] [1, 2, 3]
Eğer öntanımlı bağımsız değişken değerlerinin birbirini izleyen çağrılarla paylaşılmasını istemiyorsanız yukarıdaki işlevi şu şekilde yazabilirsiniz:
def f(a, L = None): if L is None: L = [] L.append(a) return L
4.7.2. Bağımız değişken olarak anahtar kelime
İşlevler anahtar kelime = değer
şeklindeki anahtar
kelimelerle de çağırılabilir. Örneğin şu işlev:
def otomobil(yakit, hareket=' uçar', model='Anadol'): print "Eğer", yakit, "koyarsan bu", model, hareket
aşağıdaki gibi çağırılabilir:
otomobil('roket yakıtı') otomobil(hareket = 'dans eder', yakıt = 'zeytin yağı' ) otomobil('ispirto', model = 'Kartal') otomobil('su','bozulur','Şahin')
Şu çağrılar ise hatalıdır:
otomobil() # gerekli bağımsız değişken eksik otomobil(yakıt = 'su','zeytin yağı') # anahtar kelimeden sonra gelen # anahtar kelime olmayan bağımsız değişken otomobil('mazot', yakit = 'benzin') # aynı bağımsız değişken için iki değer otomobil(sehir = 'İzmir') # bilinmeyen anahtar kelime
Genel olarak, bağımsız değişken listesinin başında konuma bağlı bağımsız değişkenler bulunur ve anahtar kelime bağımsız değişkenler onları izler; anahtar kelime adları da işlevin bağımsız değişkenlerinden seçilir. Bağımsız değişkenin öntanımlı değerlerinin olup olmaması önemli değildir. Bir bağımsız değişken birden fazla değer alamaz; konuma bağlı bağımsız değişken isimleri aynı çağrıda anahtar kelime olarak kullanılamaz. İşte bundan dolayı hatalı olan bir örnek:
>>>
def function(a):...
pass...
>>>
function(0, a=0) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: keyword parameter redefined
Eğer işlev tanımındaki son bağımsız değişken **isim
şeklinde ise bu bağımsız değişken adları herhangi bir bağımsız değişken
olmayan anahtar kelime şeklindeki bağımsız değişkenlerin bulunduğu bir
sözlük olur. Bu *isim
(bu konu Sözlükler (Çağrışımlı Listeler) bölümünde anlatılacaktır.)
şeklindeki bir bağımsız değişken ile de kullanılabilir, ki bu bağımsız
değişken listesi içinde bulunmayan konuma bağlı bağımsız değişkenleri
içeren bir demet (daha sonra Demetler (tuples)
bölümünde incelenecek bir veri türüdür) olur. *isim
bağımsız değişkeni **isim
bağımsız değişkeninden önce
gelmelidir. Buna örnek işlev:
def kasapdukkani(etCinsi,*argumanlar, **anahtarKelimeler): print "--", etCinsi, "var mi ?" print "-- Maalesef", etCinsi, "kalmadı." for arg in argumanlar: print arg print '-'*40 anahtarlar = anahtarKelimeler.keys() anahtarlar.sort() for ak in anahtarlar: print ak, ':', anahtarKelimeler[ak]
Şu şekilde çağrılabilir:
kasapdukkani('martı eti',"Çok lezzetli.", "Çok satılıyor.", musteri = 'Martı Murat', kasap = 'Dev İsmail')
ve doğal olarak şu çıktıyı verir:
-- martı eti var mi ? -- Maalesef martı eti kalmadı. Çok lezzetli. Çok satılıyor. ---------------------------------------- kasap : Dev İsmail musteri : Martı Murat
anahtarKelimeler
isimli sözlüğün içeriği yazdırılmadan
önce anahtar kelime isimleri listesinin sort()
yönteminin çağırıldığına dikkat edin; bu yapılmaz ise bağımsız
değişkenlerin hangi sıra ile yazılacağı tanımlanmamış olur.
4.7.3. Keyfî Bağımsız Değişken Listeleri
Son olarak, en ender kullanılan seçenek de keyfî sayıdaki bağımsız değişken ile çağrılabilen bir işlev tanımlamaktır. Bu bağımsız değişkenler bir demet (değişmez liste [tuple]) içine alınır. Keyfî bağımsız değişken listesinden önce sıfır ya da daha fazla normal bağımsız değişken bulunabilir. Örnek:
def fprintf(file, format, *args): file.write(format % args)
4.7.4. Lambda Biçemli İşlevler
Yoğun istek üzerine işlevsel dillerde ve Lisp'te bulunan bazı
özellikler Python'a eklenmiştir. lambda
anahtar
kelimesi ile küçük anonim işlevler yazılabilir. İşte iki
bağımsız değişkeninin toplamını geri döndüren bir işlev:
lambda a, b: a+b
.
Lambda işlevleri bir işlev nesnesine ihtiyaç duyulan her yerde kullanılabilir. Sözdizim (syntax) açısından bunlar tek bir ifade ile sınırlandırılmıştır. Anlambilim (semantics) açısından ise normal işlev tanımlamasına getirilen bir sözdizim güzelliğidir. İç içe tanımlanmış işlevlerde olduğu gibi lambda işlevleri de kendilerini kapsayan etki alanindaki değişkenlere erişebilir:
>>>
def artirici_yap(n):...
return lambda x: x + n...
>>>
f = artirici_yap(42)>>>
f(0) 42>>>
f(1) 43
4.7.5. Belgelendirme Dizgeleri
Belgelendirmede kullanılan dizgelerin şekli ve içeriği ile ilgili şartlar yeni yeni oluşmaktadır.
İlk satır daima nesnenin amacının kısa ve öz tanımı olmalıdır. Kısa olması için, nesnenin adından ve türünden bahsedilmemeli; zira bunlar başka yollarla da öğrenilebilir. Bu satır büyük harf ile başlayıp nokta ile bitmelidir.
Eğer belgelendirme dizgesinde birden fazla satır var ise ikinci satır boş olup özet ile açıklamamın devamını birbirinden ayırmalıdır. Diğer satırlar bir ya da daha fazla satır olabilir. Bunlarla nesnenin özellikleri, çağrı şekilleri, yan etkileri vs. açıklanabilir.
Python çözümleyicisi (parser) çok satırlı dizgelerdeki girintileri yok etmez; yani belgeleri işleyen yazılımlar gerekirse bunları atabilir. İlk satırdan sonra gelen ve boş olmayan ilk satırdaki girinti miktarı belgelendirme dizgesinin devamındaki girinti miktarını belirler. Bu girinti miktarına ``eşdeğer'' boşluk diğer satırların başından atılır. Daha az girintili satırlar olmamalı; ama olursa da bunların önündeki boşluğun tamamı atılmalı. Boşluğun eşdeğerliği sekmelerin genişletilmesinden (1 sekme = 8 boşluk) sonra sınanmalıdır.
İşte çok satırlı bir belgelendirme dizgesi örneği:
>>>
def benimFonksiyon():...
"""Sadece belgeler....
...
Başka birşey yapmaz. Gerçekten !....
"""...
pass...
>>>
print benimFonksiyon.__doc__ Sadece belgeler. Başka birşey yapmaz. Gerçekten !
[68] Aslında nesne başvurusu ile çağrı daha iyi bir tanım olur, çünkü işleve değiştirilebilir bir nesne aktarılırsa çağıran çağrılanın o nesneye uyguladığı tüm değişiklikleri görür (listeye eklenen elemanlar gibi).