Ek: Hatalı kod vakaları
Hatalı kod vakaları
Her vakada şu dört adımı izleyin:
- Programın ne yapması gerektiğini okuyun.
- Hatanın hangi satırda olduğunu bulun.
- Nedenini kendi cümlenizle açıklayın.
- Kodu olabildiğince az değiştirerek düzeltin, sonra en az bir sınır değeriyle yeniden deneyin.
A: Sınır ve off-by-one hataları (6 vaka)
Off-by-one hatası, döngünün ya da aralığın bir adım eksik veya bir adım fazla çalışmasıdır.
A1: 1’den 5’e kadar yazdır
Amaç: 1 2 3 4 5
for i in range(1, 5):
print(i, end=" ")Gözlenen: 1 2 3 4
A2: İlk eleman dâhil dört elemanı yazdır
Amaç: Listenin dört elemanını da yazdırmak.
sayilar = [10, 20, 30, 40]
for i in range(1, len(sayilar)):
print(sayilar[i])Gözlenen: 10 hiç yazdırılmıyor.
A3: Metnin son karakterini de al
Amaç: Python metninin tamamını yazdırmak.
metin = "Python"
print(metin[0:len(metin) - 1])Gözlenen: Pytho; son karakter dilimin dışında kalıyor.
A4: Yaş 18 ise yetişkin kabul et
yas = 18
if yas > 18:
print("Yetişkin")
else:
print("Koşul sağlanmadı")Gözlenen: Koşul sağlanmadı
A5: Listenin son indeksini aşma
Amaç: Her elemanı indeksle yazdırmak.
sayilar = [4, 8, 12]
i = 0
while i <= len(sayilar):
print(sayilar[i])
i += 1Gözlenen: İlk üç değer yazıldıktan sonra IndexError.
A6: 0 ve 100 geçerli puan olsun
puan = 100
if 0 < puan < 100:
print("Geçerli")
else:
print("Geçersiz")Gözlenen: 100 için Geçersiz.
- A1:
range(1, 6)kullanın;rangeüst sınırı dâhil etmez. - A2:
range(len(sayilar))ile0’dan başlayın ya da Python’da daha yaygın olanfor sayi in sayilaryazımını kullanın. - A3: Dilimin bitiş indeksi zaten dâhil edilmez,
- 1son karakteri de dışarıda bırakır. Metnin tamamı içinmetin[:]ya dametin[0:len(metin)]yazın. - A4: Sınır değeri dâhilse
yas >= 18yazılır. - A5:
i < len(sayilar)olmalı, çünkü son geçerli indekslen(...) - 1’dir. - A6:
0 <= puan <= 100.
B: input() ve tür dönüşümü hataları (4 vaka)
B1: Yaşa 1 ekle
yas = input("Yaş: ")
print(yas + 1)Gözlenen: TypeError.
B2: İki sayıyı topla
Örnek girdi: 10 ve 20; amaç 30.
a = input("A: ")
b = input("B: ")
print(a + b)Gözlenen: 1020.
B3: Ondalıklı fiyatı dönüştür
fiyat = input("Fiyat: ") # kullanıcı: 12.5
print(int(fiyat))Gözlenen: ValueError.
B4: Aralık kontrolü harfli girdiyi yakalamıyor
puan = int(input("Puan: ")) # kullanıcı: abc
if 0 <= puan <= 100:
print("Geçerli")
else:
print("Geçersiz")Gözlenen: if satırına gelmeden ValueError.
- B1:
yas = int(input(...))yazın ya da dönüşümü ayrı bir satırda yapın. - B2: İki girdiyi de
int()ile (ondalıklı sayı bekleniyorsafloat()ile) dönüştürün. - B3:
float(fiyat)kullanın.int(),"12.5"gibi ondalıklı bir metni tam sayıya çeviremez. - B4:
int()hata verdiği için programifsatırına hiç gelmez. 13. bölümde göreceğiniztry/except ValueErrorile dönüşüm hatasını yakalayın, ardından 0–100 aralığını kontrol edin.
C: Aliasing ve kopyalama hataları (5 vaka)
C1: Yedek listeyi bağımsız tut
notlar = [70, 80]
yedek = notlar
yedek.append(90)
print(notlar)Gözlenen: [70, 80, 90]; özgün liste de değişti.
C2: İki öğrencinin not listesi ayrı olsun
ortak = []
ada = ortak
ece = ortak
ada.append(100)
print(ece)Gözlenen: [100].
C3: Sığ kopyanın sınırı
a = [[1, 2], [3, 4]]
b = a.copy()
b[0].append(9)
print(a)Gözlenen: [[1, 2, 9], [3, 4]].
C4: Fonksiyon özgün listeyi değiştirmesin
def sirala(veri):
veri.sort()
return veri
sayilar = [3, 1, 2]
sonuc = sirala(sayilar)
print(sayilar)Gözlenen: [1, 2, 3]; özgün liste de sıralandı.
C5: “Kopya” değişkeni aslında aynı nesne
a = [1, 2]
b = a
print(a is b)Gözlenen: True; amaç bağımsız listeydi.
- C1:
yedek = notlar.copy()gibi bir sığ kopya oluşturun. - C2:
ada = []veece = []diye iki ayrı liste oluşturun. Tek bir listeyi iki değişkene atamayın. - C3: Sığ kopya yalnız dış listeyi ayırır. İç listelerin de bağımsız olması gerekiyorsa her iç listeyi ayrıca kopyalamanız gerekir, örneğin
[satir.copy() for satir in a]ile. Daha derin iç içe yapılarda derin kopya (deep copy) gerekip gerekmediğini ayrıca düşünün. - C4: Özgün liste korunacaksa
return sorted(veri)yazın ya da sıralamadan önce kopya alın. - C5:
b = a.copy()ya dab = a[:]gibi bir kopya gerekir.
D: Sonsuz döngü ve eksik ilerleme (4 vaka)
D1: Sayaç hiç değişmiyor
sayac = 1
while sayac <= 5:
print(sayac)Gözlenen: 1 sürekli yazdırılıyor.
D2: Yanlış yönde güncelleme
kalan = 3
while kalan > 0:
print(kalan)
kalan += 1Gözlenen: 3, 4, 5, ... diye devam ediyor.
D3: Geçersiz girdi değişmiyor
puan = -1
while puan < 0 or puan > 100:
print("Geçersiz")Gözlenen: döngü bitmiyor.
D4: continue güncellemeyi atlıyor
i = 0
while i < 5:
if i == 2:
continue
print(i)
i += 1Gözlenen: 0 ve 1 yazıldıktan sonra döngü hiç bitmiyor.
- D1: Gövdeye
sayac += 1ekleyin. - D2:
kalan -= 1olmalı. - D3: Döngünün içinde yeni girdi alın ya da koşulu değiştirecek başka bir değişkeni güncelleyin.
- D4:
ideğerinicontinuesatırından önce artırın ya da döngüyü her turdaiartacak biçimde yeniden yazın.
E: Kapsam ve dönüş değeri hataları (4 vaka)
E1: return unutulmuş
def kare(x):
x * x
sonuc = kare(4)
print(sonuc)Gözlenen: None.
E2: Yerel değişkeni dışarıda kullanma
def hesapla():
toplam = 10 + 20
hesapla()
print(toplam)Gözlenen: NameError.
E3: print ile return karıştırılmış
def topla(a, b):
print(a + b)
sonuc = topla(2, 3)
print(sonuc * 2)Gözlenen: önce 5, ardından TypeError (None * 2).
E4: Global adı değiştirmeye çalışırken UnboundLocalError
sayac = 0
def artir():
sayac = sayac + 1
return sayac
print(artir())Gözlenen: UnboundLocalError.
- E1:
return x * x. - E2:
toplamyalnız fonksiyonun içinde (yerel kapsamda) vardır. Değer dışarıda gerekiyorsareturn toplamile döndürün ve çağrının sonucunu bir değişkene atayın. - E3: Hesap yapan fonksiyon sonucu
return a + bile döndürmeli. Ekrana yazdırma işini fonksiyonu çağıran kod yapabilir. - E4: Önce global değişken kullanmadan çözmeyi deneyin: fonksiyon sayacı parametre olarak alsın, yeni değeri döndürsün. Global değişken gerçekten gerekiyorsa
global sayacyazılır, ama küçük fonksiyonlarda gereksiz global değişkenden kaçının.
F: İndeks ve anahtar hataları (2 vaka)
F1: Son siparişi raporla
Amaç: Listedeki son sipariş kimliği olan S-103 değerini yazdırmak.
siparisler = ["S-101", "S-102", "S-103"]
son_indeks = len(siparisler)
print(siparisler[son_indeks])Gözlenen: IndexError; len(siparisler) eleman sayısıdır, son geçerli indeks değildir.
F2: Yeni ürün gelirse stok kaydını başlat
Amaç: Gelen ürünleri mevcut stoğa eklemek; sözlükte olmayan ürünün stok sayısını 0’dan başlatmak.
stok = {"kalem": 5, "defter": 2}
gelenler = ["kalem", "silgi", "kalem"]
for urun in gelenler:
stok[urun] += 1
print(stok)Gözlenen: silgi işlenirken KeyError; program sonraki ürüne geçemiyor.
- F1: Son eleman için
siparisler[-1]ya dasiparisler[len(siparisler) - 1]yazın. Liste boş olabiliyorsa önce eleman olup olmadığını kontrol edin. - F2: Bu problemde sözlükte olmayan bir ürünün gelmesi olağan bir durum, bu yüzden
stok[urun] = stok.get(urun, 0) + 1yazın. Eksik anahtarın gerçekten bir hata olduğu başka bir problemde ise köşeli parantezle erişiminKeyErrorvermesi işinize yarayabilir.
Son kontrol
Kod artık hata vermiyor diye işi bitmiş saymayın. Düzelttiğiniz her vakayı bir normal örnekle, mümkünse bir de sınır değeri ya da geçersiz girdiyle deneyin ve programın gerçekten yapması gereken işi yaptığını görün.