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 hafta neleri yapabilmelisiniz?
if/elif/elseile karar yapısı kurabilmeli,forvewhiledöngülerini uygun durumda kullanabilmeli,breakvecontinueile döngü akışını bilinçli biçimde değiştirebilmeli,range()davranışını ve adım parametresini açıklayabilmeli,- Bir string üzerinde doğrudan dolaşabilmeli,
- İndeks ve değere birlikte gerektiğinde
enumerate()kullanabilmeli, - İki koleksiyonu paralel dolaşmak için
zip()kullanımını tanıyabilmeli, strip,split,join,replace,startswithveingibi temel string araçlarını kullanabilmeli,- Türkçe metinlerde büyük/küçük harf dönüşümünün dilsel ayrıntılar içerebileceğini fark edebilmeli,
- Kısa C döngülerini Python’a dönüştürebilmeli,
- Sınır ve off-by-one hatalarını fark edebilmelisiniz.
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:
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(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:
- Döngüyü başlatan durum nedir?
- Her turda hangi durum değişiyor?
- 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 usernameAlış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.
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.
Kendinizi kontrol edin
range(1, 5)hangi sayıları üretir?range(10, 0, -1)neden geriye sayar?for ch in textyapısındachneyi temsil eder?- Hem indeks hem değer gerekiyorsa hangi araç daha doğaldır?
breakilecontinuearasındaki fark nedir?split()vejoin()hangi ters yönlü işleri yapar?- String neden “değiştirilemez” kabul edilir?
lower()neden Türkçe metinlerde bütün dilsel eşleme problemlerini çözmez?whiledöngüsünde sonsuz döngüyü önlemek için hangi durum değişmelidir?
Bu haftadan akılda kalması gerekenler
if,forvewhilekavramları 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.breakdöngüyü bitirir;continueyalnızca mevcut turu atlar.range()son sınırı içermez ve üçüncü parametre adım değeridir.split,join,stripgibi 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.