Koşullar, döngüler ve string işlemleri

Bu hafta daha önce C’de kullandığınız karar ve tekrar yapılarını Python’a taşıyoruz. Amaç if ve döngü kavramlarını yeniden öğretmek değil; Python’daki daha sade sözdizimini ve koleksiyon/string üzerinde doğrudan dolaşma biçimini öğrenmektir.

Bu bölümün kapsamı

NoteSınavda sorulur
  • if / elif / else zincirinde sınır değerinin hangi dala düştüğü
  • koleksiyon değerleri üzerinde doğrudan dolaşma; enumerate() ve zip()
  • range() bitişinin dışarıda kalması ve adım parametresi
  • while döngüsünde durumu değiştiren adım
  • break ile continue farkı
  • string’in değiştirilemez olması
  • lower() / upper() dönüşümünün Türkçe I / İ sınırı
  • Unicode normalleştirme biçimleri ve yerel ayar (locale) kütüphaneleri
  • düzenli ifadeler
  • liste kavraması

Bu başlıklar konunun devamıdır; ileride karşınıza çıkar ama bu derste ezberlemeniz beklenmiyor.

Döngüyü sayaçla mı, değerle mi kurmalıyım?

C’den gelen ilk sezgi indeks tutmaktır. Python’da çoğu zaman değerin kendisi üzerinde dolaşmak hem daha kısa hem de niyeti daha açık yazar. İndeksin gerçekten gerektiği durumlar için enumerate() ve zip() var; bölümün ikinci yarısında aynı soruyu metin üzerinde soracağız.

if: parantez ve süslü parantez yok

Python’da koşulun sonuna : gelir; blok girintiyle belirlenir. else if yerine elif kullanılır.

Sınır değerini düşünün

score = 70 için sonuç ne olur? 69 için ne olur? Koşul zincirlerinde sınır değerlerini özellikle test etmek, görünüşte doğru kodun gizli hatalarını yakalar.

for: çoğu zaman sayaçtan daha fazlası

C’de bir string’i dolaşmak için indeks değişkeni kullanmaya alışmış olabilirsiniz. Python’da çoğu zaman elemana doğrudan erişebiliriz:

İndeks üzerinden dolaşma ile koleksiyon değerleri üzerinde doğrudan for döngüsüyle dolaşmayı karşılaştıran diyagram.

Değer üzerinde doğrudan dolaşma

Bu kodda letter, her turda sıradaki karakteri alır. İndeks gerekmediği için ayrıca sayaç tutmuyoruz.

İndeks gerçekten gerekiyorsa range() kullanılabilir; fakat Python’da hem indeks hem değer gerektiğinde çoğu zaman enumerate() daha doğrudandır:

Bu biçim, range(len(word)) yazıp her turda word[i] erişimi yapma ihtiyacını azaltır.

İki diziyi aynı anda dolaşmak istediğimizde zip() kullanılabilir:

zip() en kısa koleksiyon bittiğinde durur. Koleksiyon uzunluklarının eşit olması gerekiyorsa bunu ayrıca doğrulamak gerekir.

range() son değeri içermez

range fonksiyonunda bitiş değerinin aralığa dahil edilmediğini gösteren sınır diyagramı.

range() sınırı

range(5)0, 1, 2, 3, 4. Son sınırın dışarıda kalması, C’deki i < 5 kalıbına benzer.

range(start, stop, step) biçimindeki üçüncü parametre adım değeridir. Geriye saymak için negatif adım kullanılır:

for number in range(10, 0, -1):
    print(number)

Adımın işareti ile başlangıç/bitiş yönü uyumsuzsa aralık boş olabilir; bunu küçük bir list(range(...)) deneyiyle doğrulayabilirsiniz.

while: koşula bağlı tekrar

Tekrar sayısı baştan belli değilse while daha doğal olabilir:

while kullanırken üç soruyu sorun:

  1. Döngüyü başlatan durum nedir?
  2. Her turda hangi durum değişiyor?
  3. Döngüyü bitirecek koşul gerçekten oluşabilir mi?

Bu üç sorudan biri belirsizse sonsuz döngü riski vardır.

break ve continue

break, içinde bulunduğu en yakın döngüyü hemen bitirir. continue ise o turun kalanını atlayıp sonraki tura geçer:

Bu örnekte -1 sentinel gibi döngüyü sonlandırır; 0 ise yalnızca işlenmeden atlanır. break/continue her problemi çözmek için kullanılmamalıdır; ama niyeti daha açık kıldığı yerde yararlıdır.

String bir karakter dizisidir

Python stringleri üzerinde indeksleme, dilimleme ve çok sayıda hazır metot kullanılabilir:

String değiştirilemez (immutable). text.upper() mevcut string’i değiştirmez; yeni bir string üretir.

Bu “değiştirilebilir/değiştirilemez” ayrımı gelecek hafta listeler ve nesne referansları için önemli olacaktır.

Sık kullanılan string araçları

Araç Amaç Örnek
strip() baş/son boşlukları temizler " a ".strip()
split(sep) metni parçalara ayırır "Ada,80".split(",")
sep.join(parts) parçaları birleştirir ", ".join(names)
replace(a, b) eşleşmeleri değiştirir text.replace("-", " ")
startswith(prefix) başlangıcı test eder name.startswith("A")
in alt metin/üyelik kontrolü "py" in "python"

Özellikle split() ve strip() 5. haftadaki dosya kayıtlarını işlerken doğrudan kullanılacaktır.

Türkçe büyük/küçük harf dönüşümü uyarısı

Python’ın lower() / upper() dönüşümleri Unicode kurallarına göre çalışır; Türkçeye özgü yerel ayar (locale) uygulayan bir metin normalleştirme sistemi değildir. Özellikle I/ı ve İ/i çiftlerinde beklediğiniz dilsel eşleme ile sonuç aynı olmayabilir:

Bu yüzden “Türkçe metni büyük/küçük harf duyarsız karşılaştırıyorum” derken yalnızca lower() çağrısının bütün dilsel durumları çözdüğünü varsaymayın. Bu derste ayrıntılı yerelleştirme yapmayacağız; amaç gerçek bir sınır durumunu fark etmektir.

Alıştırma — Koşulu tamamla

Bir kullanıcı adı en az 5 karakter olmalı ve boşluk içermemelidir.

len(username) >= 5 ile " " not in username ifadelerini and ile birleştirebilirsiniz.

valid = len(username) >= 5 and " " not in username

Alıştırma — Doğrudan dolaşarak sayma

Aşağıdaki kod bir metindeki a harflerini sayıyor. Önce sonucu tahmin edin.

Burada ayrıca bir indeks sayacı tutmuyoruz; karakterler üzerinde doğrudan dolaşıyoruz. Ardından kodu büyük/küçük harf duyarsız olacak şekilde değiştirin. Örneğin "Ankara" için hem A hem a sayılmalıdır. Sonra "Iğdır" / "İzmir" gibi Türkçe örneklerde lower() davranışını ayrıca gözlemleyin ve bunun neden genel bir Türkçe metin çözümü olmadığını açıklayın.

Alıştırma — Off-by-one hatasını düzelt

Aşağıdaki program 1’den 10’a kadar sayıların toplamını üretmek istiyor; ancak sonuç eksik.

Neden 10 işlenmiyor? Yalnızca gerekli tek değeri değiştirerek düzeltin.

Alıştırma — while döngüsünü güvenli hâle getir

Bu kodu çalıştırın. Sonra break satırını kaldırırsanız ne olacağını çalıştırmadan önce açıklayın. Web sürümünde sonsuz döngüyü gerçekten çalıştırmak yerine mantığını tartışmak yeterlidir.

Küçük üretim görevi — Metin özeti

Bir metin için aşağıdaki bilgileri üreten bir program yazın:

  • Toplam karakter sayısı,
  • Boşluk sayısı,
  • Sesli harf sayısı,
  • split() ile kelime sayısı,
  • Metnin başındaki ve sonundaki boşluklar strip() ile temizlendikten sonra ilk ve son karakter.

Örnek metni değişken olarak verin; input() zorunlu değildir. En az bir for, bir if, bir enumerate() veya zip() kullanımı ve iki farklı string metodu kullanın.

Warning

Temizlenmiş metin boşsa text[0] veya text[-1] kullanmak IndexError üretir. Yalnızca boşluklardan oluşan bir metni de sınır durumu olarak düşünün ve ilk/son karaktere erişmeden önce bunu kontrol edin.

Çalışır kod teslimi: Programınızı en az normal metin, boş string ve yalnızca boşluklardan oluşan metinle çalıştırın. Üç durumun da beklenen biçimde tamamlandığını gösterin.

C’den Python’a düşünme farkı

Aşağıdaki iki yaklaşım aynı soruyu çözebilir:

# İndeks temelli
for i in range(len(text)):
    print(text[i])

# Değer temelli
for ch in text:
    print(ch)

İndekse ihtiyacınız yoksa ikinci yaklaşım daha doğrudan niyet ifade eder. Hem indeks hem değer gerekiyorsa enumerate(text) çoğu zaman üçüncü ve daha doğal seçenektir. Python öğrenirken temel hedeflerden biri, C sözdizimini Python harfleriyle yeniden yazmak değil, dilin sunduğu daha doğal ifade biçimlerini tanımaktır.

Sınav provası

Önce kendi cevabını seç; sonra cevap anahtarında her şıkkın neden doğru veya yanlış olduğunu oku. Çeldiriciler uydurma değil, bu konuda gerçekten yapılan hatalardır. Sınav maddeleri de bu mantıkla yazılır.

Madde 1. Aşağıdaki program score = 70 iken ne yazdırır?

if score >= 85:
    result = "AA"
elif score >= 70:
    result = "BB"
else:
    result = "Başarısız"

print(result)
  • A. Hiçbir şey yazmaz
  • B. BB ve Başarısız
  • C. BB
  • D. Başarısız
  • E. AA

Madde 2. Aşağıdaki iki yazım score = 90 için neden farklı sonuç verir?

# A
if score >= 50:
    durum = "Geçti"
if score >= 85:
    durum = "Yüksek"

# B
if score >= 50:
    durum = "Geçti"
elif score >= 85:
    durum = "Yüksek"
  • A. B sözdizimi hatası verir; elif daha dar bir koşulla kullanılamaz
  • B. İkisi de Yüksek üretir; elif yalnızca yazım kısaltmasıdır
  • C. Fark yalnızca score 50’nin altındayken görülür
  • D. A’da iki if bağımsız sınandığı için ikinci atama birinciyi ezer; B’de ilk koşul doğru olunca elif hiç sınanmaz
  • E. İkisi de Geçti üretir

Madde 3. Aşağıdaki program ne yazdırır?

word = "abc"
for letter in word:
    print(letter)
  • A. Alt alta 0, 1, 2
  • B. abc
  • C. Hata verir; string üzerinde doğrudan dolaşılamaz
  • D. Alt alta a b, b c, c
  • E. Alt alta a, b, c

Madde 4. Hem indeks hem değer gerektiğinde en doğrudan yazım hangisidir?

  • A. for index, letter in enumerate(word):
  • B. for i in range(len(word)): ve gövdede word[i]
  • C. for index, letter in zip(word):
  • D. for index in word:
  • E. for letter in word.index():

Madde 5. list(range(2, 7)) ne üretir?

  • A. [3, 4, 5, 6, 7]
  • B. [2, 3, 4, 5, 6]
  • C. [0, 1, 2, 3, 4, 5, 6]
  • D. [2, 3, 4, 5, 6, 7]
  • E. [2, 7]

Madde 6. Aşağıdaki program 1’den 10’a kadar sayıların toplamını yazdırmalı ama 45 yazıyor. Hangi düzeltme doğrudur?

total = 0
for number in range(1, 10):
    total += number
print(total)
  • A. range(0, 10) yazılmalıdır
  • B. for yerine while kullanılmalıdır
  • C. range(1, 11) yazılmalıdır; bitiş değeri aralığa dahil olmadığı için 10 hiç işlenmiyor
  • D. total = 1 ile başlanmalıdır
  • E. total += number + 1 yazılmalıdır

Madde 7. Aşağıdaki döngü neden hiç bitmez?

attempts = 0
password = "1234"
guess = "0000"

while guess != password:
    attempts += 1
    print("Yanlış deneme:", attempts)
  • A. print() çağrısı döngüyü yavaşlattığı için
  • B. attempts += 1 satırı koşulu sıfırladığı için
  • C. while döngüleri Python’da break olmadan bitemez
  • D. Koşulda sınanan guess değeri döngü içinde hiç değişmez; attempts artması koşulu etkilemez
  • E. != operatörü stringlerde çalışmaz

Madde 8. Aşağıdaki program ne yazdırır?

values = [10, 20, -1, 30, 0, 40]

for value in values:
    if value == -1:
        break
    if value == 0:
        continue
    print(value)
  • A. 10, 20 ve 30
  • B. 10, 20, -1, 30 ve 40
  • C. 10, 20, 30 ve 40
  • D. Hiçbir şey yazmaz
  • E. 10 ve 20

Madde 9. Aşağıdaki program ne yazdırır?

text = "python"
text.upper()
print(text)
  • A. python
  • B. PYTHON
  • C. Python
  • D. Hata verir; upper() sonucu kullanılmalıdır
  • E. None

Madde 10. Türkçe metinleri büyük/küçük harf duyarsız karşılaştırmak için yalnızca lower() kullanmak neden yetmez?

  • A. lower() yalnızca ASCII metinlerde hata verir
  • B. lower() Unicode kurallarıyla çalışır; I/ı ve İ/i çiftlerinde beklenen Türkçe eşlemeyi vermeyebilir
  • C. lower() metni değiştirdiği için karşılaştırma bozulur
  • D. Karşılaştırma için upper() kullanmak sorunu tümüyle çözer
  • E. lower() Türkçe karakterleri hiç dönüştürmez

Madde 1 — Doğru: C. İlk koşul yanlıştır; ikinci koşulda 70 >= 70 doğru olduğu için zincir orada durur.

  • A yanlış: else dalı da bulunduğu için result her durumda bir değere bağlanır.
  • B yanlış: elif zincirinde yalnızca bir dal çalışır; ilk doğru koşuldan sonra zincir biter.
  • D yanlış: else yalnızca önceki koşulların hepsi yanlışsa çalışır.
  • E yanlış: 70 >= 85 yanlıştır; ilk dal seçilmez.

Madde 2 — Doğru: D. Bağımsız if zinciri her koşulu ayrı ayrı çalıştırır; elif zinciri ilk doğru dalda durur. A Yüksek, B Geçti üretir.

  • A yanlış: Koşulların kapsam ilişkisi sözdizimini ilgilendirmez; B geçerlidir.
  • B yanlış: elif akışı değiştirir: önceki koşul doğruysa hiç değerlendirilmez.
  • C yanlış: Fark tam olarak iki koşulun birlikte doğru olduğu değerlerde ortaya çıkar.
  • E yanlış: A’daki ikinci if bağımsızdır ve doğru olduğu için değeri değiştirir.

Madde 3 — Doğru: E. for doğrudan değerler üzerinde dolaşır; letter her turda sıradaki karakterdir.

  • A yanlış: İndeksler ancak range(len(word)) veya enumerate() ile elde edilir.
  • B yanlış: Her tur ayrı bir print çağrısıdır; çıktı alt alta gelir.
  • C yanlış: String dolaşılabilir bir değerdir.
  • D yanlış: for ikili pencere üretmez; her turda tek eleman verir.

Madde 4 — Doğru: A. enumerate() her turda sıra numarası ile değeri birlikte verir; niyeti açıkça ifade eder.

  • B yanlış: Çalışır ama indeksi elle taşır; enumerate() aynı işi daha doğrudan yapar.
  • C yanlış: zip() iki ayrı koleksiyonu eşler; tek koleksiyona indeks eklemez.
  • D yanlış: Bu yazım değerleri verir, indeksleri değil.
  • E yanlış: index() bir aramanın konumunu döndürür; dolaşılabilir bir değer üretmez.

Madde 5 — Doğru: B. Başlangıç dahil, bitiş hariçtir. Bu, C’deki i < 7 kalıbına karşılık gelir.

  • A yanlış: Başlangıç değeri dahildir.
  • C yanlış: Tek argümanlı range(7) bunu üretirdi; burada başlangıç 2dir.
  • D yanlış: Bitiş değeri aralığa dahil değildir; en sık yapılan hata budur.
  • E yanlış: İki argüman sınırları verir, yalnız o iki sayıyı değil.

Madde 6 — Doğru: C. Klasik off-by-one hatasıdır. Üst sınırı bir artırmak eksik turu geri getirir.

  • A yanlış: Bu 0 ekler ama 10u hâlâ dışarıda bırakır; toplam yine 45 kalır.
  • B yanlış: Döngü türü sorun değildir; sorun aralığın üst sınırındadır.
  • D yanlış: Biriktiriciyi bozar; 1 iki kez sayılır ve sonuç yine yanlış olur.
  • E yanlış: Her terime bir eklemek toplamı 54 yapar; eksik olan tek bir turdur.

Madde 7 — Doğru: D. Bir while döngüsünün bitmesi için koşulda geçen durumun her turda değişmesi gerekir. Burada değişen değişken koşulun parçası değildir.

  • A yanlış: Hız ile sonlanma ayrı şeylerdir; döngü mantıksal olarak bitmez.
  • B yanlış: attempts koşulda geçmez; koşulu etkilemez.
  • C yanlış: Koşul yanlış olduğunda döngü kendiliğinden biter; break zorunlu değildir.
  • E yanlış: String karşılaştırması geçerlidir ve her turda True üretir.

Madde 8 — Doğru: E. -1 değerinde break döngüyü tümüyle bitirir; 30, 0 ve 40 hiç işlenmez.

  • A yanlış: break sonrasında hiçbir tur açılmaz; 30a sıra gelmez.
  • B yanlış: -1 yazdırılmadan önce break çalışır.
  • C yanlış: Bu, -1 için de continue yazılmış olsaydı çıkardı; break döngüyü sonlandırır.
  • D yanlış: İlk iki değer break satırına gelmeden yazdırılır.

Madde 9 — Doğru: A. String değiştirilemezdir. upper() yeni bir string üretir; sonuç bir ada atanmadığı için kaybolur.

  • B yanlış: Bunun için text = text.upper() yazılması gerekirdi.
  • C yanlış: upper() yalnızca ilk harfi değil bütün harfleri büyütür; ayrıca burada hiç uygulanmıyor.
  • D yanlış: Kullanılmayan bir dönüş değeri hata üretmez; sessizce atılır.
  • E yanlış: print(text) adı yazdırır; metot çağrısının dönüşünü değil.

Madde 10 — Doğru: B. Dönüşüm yerel ayar uygulamaz. "I".lower() sonucu idir; Türkçede beklenen karşılık ıdır.

  • A yanlış: Hata yükselmez; sorun sessiz bir eşleşmemedir.
  • C yanlış: String değiştirilemez; lower() yeni bir metin üretir.
  • D yanlış: Aynı sorun ters yönde çıkar; yön değiştirmek dilsel eşlemeyi düzeltmez.
  • E yanlış: Öö gibi çoğu çift doğru dönüşür; sorun yalnızca noktalı/noktasız i ailesindedir.

Tek sayfa özet

  • if, for ve while kavramları aynı; Python’daki ifade biçimi daha sadedir.
  • for, yalnızca sayı sayacı değildir; bir veri dizisinin elemanları üzerinde doğrudan dolaşabilir.
  • enumerate() indeks + değer, zip() paralel dolaşma ihtiyacını açık ifade eder.
  • break döngüyü bitirir; continue yalnızca mevcut turu atlar.
  • range() son sınırı içermez ve üçüncü parametre adım değeridir.
  • split, join, strip gibi string araçları gerçek veri işleme görevlerinin temelidir.
  • String immutable’dır; metotların çoğu yeni string üretir.
  • Unicode büyük/küçük harf dönüşümü ile Türkçeye özgü dilsel eşleme aynı şey değildir.
  • Sınır değerleri ve off-by-one hataları hâlâ önemlidir.

Gelecek hafta Python koleksiyonlarını kullanacak ve nesne tabanlı programlama için kritik olan referans ve değiştirilebilirlik fikrine yaklaşacağız.

Bu bölümün kazanımları

Bu bölümü bitiren öğrenci:

  • if/elif/else zincirinde sınır değerinin hangi dala düştüğünü belirler.
  • Koleksiyon değerleri üzerinde doğrudan dolaşır; enumerate() ve zip() ihtiyacını ayırır.
  • range() bitiş değerinin dışarıda kaldığını bilir ve adım parametresini kullanır.
  • while döngüsünde durumu değiştiren adımın sonsuz döngüyü önlediğini açıklar.
  • break ile continue arasındaki farkı gösterir.
  • String’in değiştirilemez olduğunu ve metotların yeni string ürettiğini belirler.
  • lower() / upper() dönüşümünün Türkçe I / İ eşlemesini çözmediğini açıklar.
Back to top