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ı
if/elif/elsezincirinde sınır değerinin hangi dala düştüğü- koleksiyon değerleri üzerinde doğrudan dolaşma;
enumerate()vezip() range()bitişinin dışarıda kalması ve adım parametresiwhiledöngüsünde durumu değiştiren adımbreakilecontinuefarkı- string’in değiştirilemez olması
lower()/upper()dönüşümünün TürkçeI/İ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:
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.
Tek sayfa özet
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.
Bu bölümün kazanımları
Bu bölümü bitiren öğrenci:
if/elif/elsezincirinde sınır değerinin hangi dala düştüğünü belirler.- Koleksiyon değerleri üzerinde doğrudan dolaşır;
enumerate()vezip()ihtiyacını ayırır. range()bitiş değerinin dışarıda kaldığını bilir ve adım parametresini kullanır.whiledöngüsünde durumu değiştiren adımın sonsuz döngüyü önlediğini açıklar.breakilecontinuearası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çeI/İeşlemesini çözmediğini açıklar.