• Sonuç bulunamadı

söyle yap else:

pass

Burada henüz else blo˘gunda ne yapılaca˘gına karar vermemi¸s oldu˘gunuz için, oraya birpass koyarak durumu ¸simdilik geçi¸stiriyorsunuz. Program son haline gelene kadar oraya bir ¸seyler yazmı¸s olaca˘gız.

Sözün özü, pass deyimlerini, herhangi bir i¸slem yapılmasının gerekli olmadı˘gı durumlar için kullanıyoruz.. ˙Ilerde i¸se yarar programlar yazdı˘gınızda, bu pass deyiminin göründü˘günden daha faydalı bir araç oldu˘gunu anlayacaksınız...

8.4 “continue” Deyimi

continue ilginç bir deyimdir. ˙Isterseniz continue‘yi anlatmaya çalı¸smak yerine bununla ilgili bir örnek verelim:

>>> while True:

... s = input("Bir sayı girin: ") ... if s == "iptal":

... break

... if len(s) <= 3:

... continue

... print("En fazla üç haneli bir sayı girebilirsiniz.")

Burada e˘ger kullanıcı klavyede “iptal” yazarsa programdan çıkılacaktır. Bunu;

if s == "iptal":

break

satırıyla sa˘glamayı ba¸sardık.

E˘ger kullanıcı tarafından girilen sayı üç haneli veya daha az haneli bir sayı ise, continue ifadesinin etkisiyle:

>>> print("En fazla üç haneli bir sayı girebilirsiniz.")

satırı es geçilecek ve döngünün en ba¸sına gidilecektir.

E˘ger kullanıcının girdi˘gi sayıdaki hane üçten fazlaysa ekrana:

En fazla üç haneli bir sayı girebilirsiniz.

cümlesi yazdırılacaktır.

Dolayısıyla buradan anladı˘gımıza göre, continue deyiminin görevi kendisinden sonra gelen her ¸seyin es geçilip döngünün ba¸sına dönülmesini sa˘glamaktır. Bu bilgiye göre, yukarıdaki pro-gramda e˘ger kullanıcı, uzunlu˘gu 3 karakterden az bir sayı girersecontinue deyiminin etkisiyle

programımız döngünün en ba¸sına geri gidiyor. Ama e˘ger kullanıcı, uzunlu˘gu 3 karakterden fa-zla bir sayı girerse, ekrana “En fafa-zla üç haneli bir sayı girebilirsiniz,” cümlesinin yazdırıldı˘gını görüyoruz.

8.5 else... finally...

Python’da hata yakalama i¸slemleri için ço˘gunlukla try... except... bloklarını bilmek yeterli olacaktır. ˙I¸slerimizin büyük kısmını sadece bu blokları kullanarak halledebiliriz. An-cak Python bize bu konuda, zaman zaman i¸simize yarayabilecek ba¸ska araçlar da sunmak-tadır. ˙I¸steelse... finally blokları da bu araçlardan biridir. Bu bölümde kısaca else... ve finally... bloklarının ne i¸se yaradı˘gından söz edece˘giz.

Öncelikle else... blo˘gunun ne i¸se yaradı˘gına bakalım. Esasında biz bu else deyimini daha önce de “ko¸sullu ifadeler” konusunu i¸slerken görmü¸stük. Buradaki kullanımı da zaten hemen hemen aynıdır. Diyelim ki elimizde ¸söyle bir ¸sey var:

try:

bölünen = int(input("bölünecek sayı: ")) bölen = int(input("bölen sayı: ")) print(bölünen/bölen)

except ValueError:

print("hata!")

Burada e˘ger kullanıcı sayı yerine harf girerse “ValueError” hatası alırız. Bu hatayı “except Val-ueError:” ifadesiyle yakalıyoruz ve hata verildi˘ginde kullanıcıya uyarı vererek programımızın çökmesini engelliyoruz. Ama biliyoruz ki, bu kodları çalı¸stırdı˘gımızda Python’un verebilece˘gi tek hata “ValueError” de˘gildir. E˘ger kullanıcı bir sayıyı 0’a bölmeye çalı¸sırsa Python “Zero-DivisionError” adlı hatayı verecektir. Dolayısıyla bu hatayı da yakalamak için ¸söyle bir ¸sey yazabiliriz:

try:

bölünen = int(input("bölünecek sayı: ")) bölen = int(input("bölen sayı: ")) print(bölünen/bölen)

except ValueError:

print("hata!")

except ZeroDivisionError:

print("Bir sayıyı 0’a bölemezsiniz!")

Bu ¸sekilde hem “ValueError” hatasını hem de “ZeroDivisionError” hatasını yakalamı¸s oluruz...

Bu kodların özelli˘gi, except... bloklarının tek bir try... blo˘gunu temel almasıdır. Yani biz burada bütün kodlarımızı tek birtry... blo˘gu içine tıkı¸stırıyoruz. Bu blok içinde gerçekle¸sen hataları da daha sonra tek tek except... blokları yardımıyla yakalıyoruz. Ama e˘ger biz is-tersek bu kodlarda verilebilecek hataları gruplamayı da tercih edebiliriz:

try:

bölünen = int(input("bölünecek sayı: ")) bölen = int(input("bölen sayı: ")) except ValueError:

print("hata!") else:

try:

print(bölünen/bölen)

except ZeroDivisionError:

print("Bir sayıyı 0’a bölemezsiniz!")

Burada yaptı˘gımız ¸sey ¸su: ˙Ilk try... except... blo˘gu yardımıyla öncelikle “int(input())”

fonksiyonu ile kullanıcıdan gelecek verinin sayı olup olmadı˘gını denetliyoruz. Ardından bir

“else...” blo˘gu açarak, bunun içinde ikinci try... except... blo˘gumuzu devreye sokuy-oruz. Burada da bölme i¸slemini gerçekle¸stiriyoruz. Kullanıcının bölme i¸slemi sırasında “0”

sayısını girmesi ihtimaline kar¸sı da “except ZeroDivisionError” ifadesi yardımıyla olası hatayı gö˘güslüyoruz... Bu ¸sekilde bir kodlamanın bize getirece˘gi avantaj, hatalar üzerinde belli bir kontrol sa˘glamamıza yardımcı olmasıdır. Yukarıdaki kodlar sayesinde hatalara bir nevi “teker teker gelin!” mesajı vermi¸s oluyoruz!... Böylelikle her blok içinde sadece almayı bekledi˘gimiz hatayı kar¸sılıyoruz. Mesela yukarıda ilk try... blo˘gu içindeki dönü¸stürme i¸slemi yalnızca

“ValueError” hatası verebilir. else: blo˘gundan sonraki try... blo˘gunda yer alan i¸slem ise ancak “ZeroDivisionError” verecektir. Biz yukarıda kullandı˘gımız yapı sayesinde her bir hatayı tek tek ve yeri geldi˘ginde kar¸sılıyoruz. Bu durumun aksine, bölümün ilk ba¸sında verdi˘gimiz try... blo˘gunda hem “ValueError” hem de “ZeroDivisionError” hatalarının gerçekle¸sme ih-timali bulunuyor. Dolayısıyla biz orada bütün hataları tek bir try... blo˘gu içine sıkı¸stırmı¸s oluyoruz. ˙I¸ste else: blo˘gu bu sıkı¸sıklı˘gı gidermi¸s oluyor. Ancak sizi bir konuda uyarmak is-terim: Bu yapı, her akla geldi˘ginde kullanılacak bir yapı de˘gildir. Büyük programlarda bu tarz bir kullanım kodlarınızın darmada˘gın olmasına, kodlarınız üzerindeki denetimi tamamen kay-betmenize yol açabilir. Sonunda da elinizde bölük pörçük bir kod yı˘gını kalabilir... Zaten açıkça söylemek gerekirsetry... except... else... yapısının çok geni¸s bir kullanım alanı yok-tur. Bu yapı ancak çok nadir durumlarda kullanılmayı gerektirebilir. Dolayısıyla bu üçlü yapıyı hiç kullanmadan bir ömrü rahatlıkla geçirebilirsiniz...

try... except... else... yapılarının dı¸sında, Python’un bize sundu˘gu bir ba¸ska yapı da try... except... finally... yapılarıdır... Bunu ¸söyle kullanıyoruz:

try:

...bir takım i¸sler...

except birHata:

...hata alınınca yapılacak i¸slemler...

finally:

...hata olsa da olmasa da yapılması gerekenler...

finally.. blo˘gunun en önemli özelli˘gi, programın çalı¸sması sırasında herhangi bir hata gerçekle¸sse de gerçekle¸smese de i¸sletilecek olmasıdır. E˘ger yazdı˘gınız programda mutlaka ama mutlaka i¸sletilmesi gereken bir kısım varsa, o kısmıfinally... blo˘gu içine yazabiliriz.

finally... blo˘gu özellikle dosya i¸slemlerinde i¸simize yarayabilir. Henüz Python’da dosyalarla nasıl çalı¸saca˘gımızı ö˘grenmedik, ama ben ¸simdilik size en azından dosyalarla çalı¸sma prensibi hakkında bir ¸seyler söyleyeyim.

Genel olarak Python’da dosyalarla çalı¸sabilmek için öncelikle bilgisayarda bulunan bir dosyayı okuma veya yazma kipinde açarız. Dosyayı açtıktan sonra bu dosyayla ihtiyacımız olan bir-takım i¸slemler gerçekle¸stiririz. Dosyayla i¸simiz bittikten sonra ise dosyamızı mutlaka kapat-mamız gerekir. Ancak e˘ger dosya üzerinde i¸slem yapılırken bir hata ile kar¸sıla¸sılırsa dosyamızı kapatma i¸slemini gerçekle¸stirdi˘gimiz bölüme hiç ula¸sılamayabilir. ˙I¸stefinally... blo˘gu böyle bir durumda i¸simize yarayacaktır:

try:

dosya = open("dosyaadı", "r")

...burada dosyayla bazı i¸slemler yapıyoruz...

...ve ansızın bir hata olu¸suyor...

except IOError:

print("bir hata olu¸stu!")

finally:

dosya.close()

Burada finally... blo˘gu içine yazdı˘gımız “dosya.close()” ifadesi dosyamızı kapatmaya yarıyor. Bu blok, yazdı˘gımız program hata verse de vermese de i¸sletilecektir.

8.6 except... as...

Python’daki hata mesajları temel olarak iki bölümden olu¸sur:

1. Hatanın adı,

2. Hatanın adı ile birlikte gösterilen mesaj.

Bir örnek üzerinde görelim bunu:

ValueError: invalid literal for int() with base 10: ’a’

Burada “ValueError” hatanın adıdır. “invalid literal for int() with base 10: ‘a”’ ise gösterilen mesaj... Biz e˘ger istersek bu hatanın adını özelle¸stirebilir, o kısma istedi˘gimiz ba¸ska bir ifade yazabiliriz. Bunun içinexcept... as... bloklarından yararlanaca˘gız. Hemen bir örnek vere-lim:

try:

bölünen = int(input("bölünecek sayı: ")) bölen = int(input("bölen sayı: ")) print(bölünen/bölen)

except ZeroDivisionError as hata:

print("Sıfıra Bölme Hatası. Python ¸su hata mesajını verdi:", hata)

Burada “ZeroDivisionError” adlı hatayı aslında bile¸senlerine ayırmı¸s olduk... “except Zero-DivisionError as hata” ifadesi yardımıyla bu hata mesajının ana gövdesini “hata” olarak ad-landırdık. Son olarak da bu “hata” de˘gi¸skenini print() fonksiyonu içinde kullanarak ekrana yazdırdık.

8.7 raise

Bazen, yazdı˘gımız bir programda, kullanıcının yaptı˘gı bir i¸slem normal ¸sartlar altında hata ver-meyecek olsa bile biz ona “Python tarzı” bir hata mesajı göstermek isteyebiliriz. Böyle bir du-rumda ihtiyacımız olan ¸sey Python’un bize sundu˘guraise adlı deyimdir. Bu deyim yardımıyla duruma özgü hata mesajları üretebiliriz. Bir örnek verelim:

bölünen = int(input("bölünecek sayı: ")) if bölünen == 23:

raise Exception("Bu programda 23 sayısını görmek istemiyorum!")

bölen = int(input("bölen sayı: ")) print(bölünen/bölen)

Burada e˘ger kullanıcı “23” sayısını girerse, kullanıcıya bir hata mesajı gösterilip programdan çıkılacaktır... Biz bu kodlarda “Exception” adlı genel hata mesajını kullandık. Burada “Ex-ception” yerine her istedi˘gimizi yazamayız. Yazabileceklerimiz ancak Python’da tanımlı hata mesajları olabilir. Örne˘gin NameError, TypeError, ZeroDivisionError, IOError, vb...

raise deyimini, bir hata mesajına ek olarak bir i¸slem yapmak istedi˘gimizde de kullanabiliriz.

Örne˘gin:

try:

bölünen = int(input("bölünecek sayı: ")) bölen = int(input("bölen sayı: ")) print(bölünen/bölen)

except ZeroDivisionError:

print("bir sayıyı 0’a bölemezsiniz") raise

Burada, e˘ger kullanıcı bir sayıyı 0’a bölmeye çalı¸sırsa, normal bir ¸sekilde “ZeroDivisionError”

hatası verilecek ve programdan çıkılacaktır. Ama bu hata mesajıyla birlikte kullanıcıya “bir sayıyı 0’a bölemezsiniz” uyarısını da gösterme imkanını elde edece˘giz... Yani burada “except ZeroDivisionError” blo˘gunu herhangi bir hatayı engellemek için de˘gil, hataya ilave bilgi ekle-mek için kullanıyoruz. Bunu yapmamızı sa˘glayan ¸sey tabii ki bu kodlar içinde görünenraise adlı deyimdir...

8.8 Bütün Hataları Yakalamak

¸

Simdiye kadar yaptı˘gımız bütün örneklerdeexcept... blo˘gunu bir hata mesajı adıyla birlikte kullandık. Yani örneklerimiz ¸suna benziyordu:

try:

....birtakım i¸sler...

except ZeroDivisionError:

...hata mesajı...

Yukarıdaki kod yardımıyla sadece “ZeroDivisionError” adlı hatayı yakalayabiliriz. E˘ger yazdı˘gımız program ba¸ska bir hata daha veriyorsa, o hata mesajı yukarıdaki blokların kap-samı dı¸sında kalacaktır. Ama e˘ger istersek yukarıdaki kodu ¸su ¸sekilde yazarak olası bütün hataları yakalayabiliriz:

try:

....birtakım i¸sler...

except:

...hata mesajı...

Gördü˘günüz gibi, burada herhangi bir hata adı belirtmedik. Böylece Python, yazdı˘gımız pro-gramda hangi hata olu¸sursa olu¸ssun hepsini yakalayabilecektir.

Bu yöntem gözünüze çok pratik görünmü¸s olabilir, ama aslında hiç de öyle sayılmaz. Hatta oldukça kötü bir yöntem oldu˘gunu söyleyebiliriz bunun. Çünkü bu tarz bir kod yazımının bazı dezavantajları vardır. Örne˘gin bu ¸sekilde bütün hata mesajlarını aynı kefeye koyarsak, pro-gramımızda ne tür bir hata olu¸sursa olu¸ssun, kullanıcıya hep aynı mesajı göstermek zorunda

kalaca˘gız. Bu da, herhangi bir hata durumunda kullanıcıyı ne yapması gerekti˘gi konusunda do˘gru düzgün bilgilendiremeyece˘gimiz anlamına geliyor. Yani kullanıcı bir hataya sebep oldu˘gunda tersli˘gin nereden kaynaklandı˘gını tam olarak kestiremeyecektir.

Ayrıca, e˘ger kendimiz bir program geli¸stirirken sürekli olarak bu tarz bir yazımı benimsersek, kendi kodlarımızdaki hataları da maskelemi¸s oluruz. Dolayısıyla, Python yukarıdaki geni¸s çaplı except... blo˘gu nedeniyle programımızdaki bütün hataları gizleyece˘gi için, programımızdaki potansiyel aksaklıkları görme imkanımız olmaz. Dolayısıyla bu tür bir yapıdan olabildi˘gince kaçınmakta fayda var...

BÖLÜM

9