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