Metin her yerde
Anadolu Market'in müşteri tablosunda e-posta adresleri bazen büyük harfli, bazen başında boşluklu; şehir alanında "istanbul", "İstanbul" ve "ISTANBUL" aynı anda var. Veri temizliğinin büyük kısmı metin (string) işlemidir. Python'ın metin desteği bu yüzden zengindir: dilimleme, onlarca metot ve f-string biçimleme.
Metin oluşturma ve temel işlemler
ad = "Ayşe"
soyad = 'Yılmaz'
tam_ad = ad + " " + soyad # birleştirme
print(tam_ad)
print(len(tam_ad)) # karakter sayısı
print("-" * 10) # tekrar
print("Yıl" in tam_ad) # içeriyor mu?
adres = """Atatürk Cad. No: 5
Konak / İzmir"""
print(adres)
Üç tırnak, satır sonlarını içeren uzun metinler için. len karakter sayısını verir; Türkçe karakterler de tek karakter sayılır. in operatörü bir parçanın metinde geçip geçmediğini True/False olarak söyler ve büyük-küçük harfe duyarlıdır.
İndeks ve dilimleme
Metin, sıralı karakterlerden oluşur ve her karakterin bir konumu (index) vardır. Sayma 0'dan başlar; negatif indeks sondan sayar. Dilimleme (slicing) metin[baslangic:bitis] biçiminde bir parça alır; başlangıç dahil, bitiş hariçtir.
siparis_kodu = "AM-2025-IZM-00417" print(siparis_kodu[0]) # A print(siparis_kodu[-1]) # 7 print(siparis_kodu[3:7]) # 2025 (yıl) print(siparis_kodu[8:11]) # IZM (şehir) print(siparis_kodu[-5:]) # 00417 (sıra no) print(siparis_kodu[:2]) # AM print(siparis_kodu[::-1]) # ters çevir
Sınırı boş bırakırsan baştan ya da sona kadar gider. Üçüncü değer adımdır: [::2] ikide bir, [::-1] ters sıra. Var olmayan tek bir indeks (siparis_kodu[50]) IndexError verir, ama dilim sınırı aşarsa sessizce elindekini verir.
| İfade | Sonuç | Açıklama |
|---|---|---|
s[0] | ilk karakter | sayma 0'dan başlar |
s[-1] | son karakter | negatif sondan sayar |
s[2:5] | 2, 3, 4. karakterler | bitiş hariç |
s[:3] | ilk 3 karakter | baştan |
s[3:] | 3'ten sona | sona kadar |
s[::-1] | ters metin | adım -1 |
Metotlar: metni dönüştürmek
Metot (method), bir değere ait fonksiyondur ve nokta ile çağrılır. Metin metotları metni değiştirmez, yeni bir metin döndürür; bu yüzden sonucu bir değişkene atarsın.
ham = " ayse.yilmaz@ANADOLUMARKET.com "
temiz = ham.strip().lower()
print(repr(temiz))
print(temiz.upper())
print(temiz.replace(".com", ".com.tr"))
print(temiz.find("@")) # @ işaretinin konumu
print(temiz.startswith("ayse"), temiz.endswith(".com"))
print("İzmir".upper(), "İZMİR".lower())
strip baştaki ve sondaki boşlukları (ve satır sonlarını) temizler; lstrip ve rstrip tek taraflı çalışır. repr metni tırnaklarıyla gösterir; boşlukların gerçekten gittiğini görmek için işe yarar. find aranan parçanın ilk konumunu, bulamazsa -1 döndürür. Metotlar zincirlenebilir: ham.strip().lower() önce temizler, sonra küçültür.
"İzmir".upper() doğru şekilde İZMİR verir, ama "İZMİR".lower() sonucu i̇zmi̇r gibi noktalı ek karakterler içerebilir; bu Unicode'un İ harfini iki parça olarak ele almasından kaynaklanır. Karşılaştırma yapmadan önce casefold() kullanmak ya da İ/I harflerini elle replace etmek daha güvenlidir.split ve join: parçala, birleştir
Veri genellikle ayraçla gelir: "İzmir,Konak,35220" gibi. split metni ayraçtan böler ve liste döndürür; join bir listeyi ayraçla birleştirir. İkisi birbirinin tersidir.
satir = "İzmir,Konak,35220"
parcalar = satir.split(",")
print(parcalar)
print(parcalar[0], "-", parcalar[2])
kelimeler = " Kahve Makinesi Siyah ".split()
print(kelimeler)
print(" ".join(kelimeler))
print(" | ".join(["Ad", "Şehir", "Tutar"]))
split() ayraçsız çağrılırsa her türlü boşluktan böler ve fazla boşlukları yok sayar; dağınık metni kelimelere ayırmanın en kolay yolu budur. join'in yazımına dikkat: ayraç önde, liste parantez içinde. Listeleri ilerideki Listeler dersinde ayrıntılı göreceksin.
f-string: değişkeni metne yerleştirmek
Rapor satırı üretmek için + ile birleştirmek hem yorucu hem hataya açıktır (sayıları str'ye çevirmek gerekir). f-string çözümdür: tırnağın önüne f koy, süslü parantez içine değişken ya da ifade yaz.
musteri = "Ayşe Yılmaz"
tutar = 1499.9
adet = 3
print(f"Sayın {musteri}, {adet} ürün için toplam {adet * tutar} TL.")
print(f"Tutar: {tutar:.2f} TL") # 2 ondalık
print(f"Toplam: {adet * tutar:,.2f} TL") # binlik ayraç
print(f"{'Ürün':<12}{'Adet':>6}") # hizalama
print(f"{'Kahve':<12}{adet:>6}")
İki nokta sonrası biçim belirtimidir: .2f iki ondalık, , binlik ayraç, <12 sola yaslayıp 12 karaktere tamamla, >6 sağa yasla. String Biçimleme dersinde bunu derinleştireceğiz; şimdilik bu dört kalıp raporların çoğunu karşılar.
{adet * tutar} gibi hesap, {ad.upper()} gibi metot çağrısı yazabilirsin. Ama çok uzun ifadeyi önce değişkene al; okunurluk önce gelir.Metin kontrolleri
Veri doğrulamada bazı sorular çok sık sorulur: bu değer yalnızca rakamdan mı oluşuyor, boş mu, belirli bir ekle mi bitiyor? Metin metotları bu sorulara True/False ile cevap verir.
posta_kodu = "35220"
print(posta_kodu.isdigit())
print("abc12".isalpha(), "abc".isalpha())
print("".strip() == "", " ".strip() == "")
dosya = "rapor_2025.csv"
print(dosya.endswith(".csv"), dosya.startswith("rapor"))
print("İZMİR".isupper(), "izmir".islower())
print("kahve makinesi".title())
"-5".isdigit() False döner çünkü eksi işareti rakam değildir; ama int("-5") çalışır. Boşluklu " 42 " için de isdigit False'tur. Doğrulamadan önce strip uygula, işaretli sayı bekliyorsan isdigit yerine dönüşümü deneyip hatayı yakala.Değişmezlik (immutability)
Metinler değişmezdir: oluşturduktan sonra tek bir karakterini bile yerinde değiştiremezsin. ad[0] = "a" TypeError verir. Metotlar yeni metin döndürür ve eski metin olduğu gibi kalır; bu yüzden ad.upper() yazıp sonucu kullanmazsan hiçbir şey değişmez.
sehir = "izmir" sehir.upper() # sonuç kayboldu print(sehir) sehir = sehir.upper() # yeni metni aynı ada bağla print(sehir) yeni = "İ" + sehir[1:] # ilk harfi değiştirmek: yeni metin kur print(yeni)
Değişmezlik ilk bakışta kısıtlama gibi dursa da bir güvencedir: bir metni fonksiyona verdiğinde fonksiyonun onu bozmayacağını bilirsin. Listelerde bu güvence yoktur ve bunun sonuçlarını Listeler dersinde göreceksin.
Unicode, Türkçe İ/ı sorunu ve kodlamalar Unicode ve metin kodlaması dersinde, biçim belirtimlerinin tamamı String biçimleme dersinde. Bu bölüm, günlük veri işinde en çok kullanılan ama temel derste yer bulamayan metin araçlarını topluyor.
Metot haritası
str türünün kırktan fazla metodu var. Hepsini ezberlemen gerekmez; ama hangi işin hazır bir metodu olduğunu bilmek seni gereksiz kod yazmaktan kurtarır.
| Amaç | Metotlar | Not |
|---|---|---|
| Arama | find, rfind, index, count, in | find bulamazsa -1, index ValueError |
| Önek / sonek | startswith, endswith, removeprefix, removesuffix | startswith demet de alır |
| Bölme | split, rsplit, partition, rpartition, splitlines | maxsplit ile en fazla N kez böl |
| Temizleme | strip, lstrip, rstrip | Parametre bir karakter KÜMESİDİR |
| Hizalama | ljust, rjust, center, zfill | Sabit genişlikli çıktı |
| Harf | lower, upper, title, capitalize, casefold | Karşılaştırma için casefold |
| Değiştirme | replace, translate + str.maketrans | replace'in üçüncü parametresi adet |
| Denetim | isdigit, isalpha, isalnum, isspace | Boş metinde hepsi False |
Bölmenin ince ayarları: maxsplit, rsplit, partition
Gerçek veride ayraç, alanın kendi içinde de geçebilir. Bir log satırının mesaj kısmında iki nokta, bir adresin içinde virgül olabilir. Bu yüzden "en fazla kaç kez böleceğini" söylemek önemlidir.
log = "2025-03-14 09:41:07 ERROR Ödeme reddedildi: kart limiti yetersiz"
tarih, saat, seviye, mesaj = log.split(" ", 3) # en fazla 3 kez böl
print(seviye, "|", mesaj)
dosya = "rapor.2025.mart.csv"
ad, uzanti = dosya.rsplit(".", 1) # sağdan bir kez böl
print(ad, "->", uzanti)
anahtar, ayrac, deger = "SUBE=Konak=Merkez".partition("=")
print(anahtar, "|", ayrac, "|", deger)
print("ayraç yok".partition("=")) # her zaman 3 parça
satirlar = "AM-101\nAM-102\r\nAM-103\n".splitlines()
print(satirlar)partition her zaman üç elemanlı bir demet döndürür: önce, ayraç, sonra. Ayraç yoksa ikinci ve üçüncü eleman boş metindir; bu sayede açma (unpacking) hiç hata vermez. splitlines ise Windows (\r\n) ve Unix (\n) satır sonlarını aynı anda tanır; split("\n") Windows dosyalarında satır sonlarına \r bırakır.
strip tuzağı ve removeprefix
strip, lstrip ve rstrip bir parametre alabilir, ama bu parametre bir önek değil karakter kümesidir: "baştan, bu karakterlerden herhangi biri olduğu sürece sil" der. Python 3.9 ile gelen removeprefix / removesuffix ise tam olarak verdiğin metni, yalnızca bir kez siler.
kod = "SKU-KS-0042"
print(kod.lstrip("SKU-")) # S, K, U, - bitene kadar siler: "0042"
print(kod.removeprefix("SKU-")) # yalnız öneki siler: "KS-0042"
print("rapor_rapor.csv".removesuffix(".csv"))
print("00042".lstrip("0"), "42".zfill(6))
print("***İndirim***".strip("*"))lstrip("SKU-") çoğu kodda doğru çalışıyor gibi görünür, ta ki ürün kodu S, K ya da U harfiyle başlayana kadar. Bu tür hatalar testte değil canlıda çıkar. Bir öneki silmek istiyorsan her zaman removeprefix kullan.Hizalama ve dolgu
Terminal raporu, sabit genişlikli banka dosyası ya da fiş çıktısı üretirken sütunları hizalaman gerekir. f-string biçimleme bunu yapar, ama metot karşılıkları da bilinmeye değer: ljust sola, rjust sağa, center ortaya yaslar; zfill soluna sıfır ekler.
print("ANADOLU MARKET".center(30, "="))
print("Ürün".ljust(18) + "Adet".rjust(5) + "Tutar".rjust(7))
print("Kahve Makinesi".ljust(18) + "1".rjust(5) + "1500".rjust(7))
print("Filtre Kahve".ljust(18) + "3".rjust(5) + "360".rjust(7))
print("-" * 30)
print("Fiş no:", "417".zfill(8))translate: çok karakteri tek seferde değiştirmek
Beş farklı harfi değiştirmek için beş kez replace zincirlemek yerine bir dönüşüm tablosu kurabilirsin. str.maketrans("eski", "yeni") iki eşit uzunlukta metni karakter karakter eşler; üçüncü parametre silinecek karakterleri verir. URL, dosya adı ya da sistem kodu üretirken Türkçe karakterleri ASCII'ye çevirmenin en temiz yoludur.
TR_ASCII = str.maketrans("çğıöşüÇĞİÖŞÜ", "cgiosuCGIOSU", "'")
baslik = "Şükrü'nün Ödeme Çizelgesi"
print(baslik.translate(TR_ASCII))
print(baslik.translate(TR_ASCII).lower().replace(" ", "-"))Metin karşılaştırma ve birkaç küçük ayrıntı
- Sözlük sırası: Metinler karakter karakter, kod numarasına göre karşılaştırılır. Büyük harfler küçüklerden önce gelir (
"Z" < "a") ve rakam olarak yazılmış sayılar metin gibi sıralanır:"10" < "9"True'dur. Sayı karşılaştıracaksan önce çevir. - Demetle önek/sonek:
dosya.endswith((".csv", ".xlsx"))birden fazla uzantıyı tek seferde sorar. - replace adedi:
"a-b-c".replace("-", "/", 1)yalnızca ilk eşleşmeyi değiştirir. - Bitişik metinler: Yan yana yazılan metin sabitleri birleşir:
("Anadolu " "Market"). Uzun metinleri parantez içinde satırlara bölmenin PEP 8 uyumlu yoludur.
print("10" < "9", 10 < 9)
print("Zeytin" < "armut", "zeytin" < "armut")
dosya = "ciro_mart.XLSX"
print(dosya.lower().endswith((".csv", ".xlsx")))
print("2025-03-14".replace("-", "/", 1))
mesaj = ("Sayın müşterimiz, siparişiniz "
"kargoya verilmiştir.")
print(mesaj)**** **** **** 9012), IBAN dörder hanelik gruplara ayrılarak okunur hâle getirilir. Bu fonksiyonlar tamamen bu bölümdeki araçlarla, dilimleme, replace, rjust ve join ile yazılır. Maskelemeyi veriyi loga yazmadan önce yapmak gerekir; sonradan log dosyasını temizlemek çok daha zordur.Veri temizliğinin standart hattı
Kurumsal müşteri verisi temizlerken neredeyse hep aynı zincir kurulur: deger.strip().casefold() ile normalize et, replace ile bilinen yazım hatalarını düzelt, split ile alanlara ayır, sonra karşılaştır. Bu zincir, "İstanbul", " istanbul " ve "ISTANBUL" değerlerini tek şehre indirir. pandas'ta aynı metotlar .str erişimcisi altında vardır; burada öğrendiğin her şey oraya taşınır.
Metin birleştirmede performans
Döngü içinde binlerce kez metin += parca yapmak her seferinde yeni metin oluşturduğu için yavaştır. Pythonic yol, parçaları bir listede biriktirip sonda "".join(liste) ile tek seferde birleştirmektir. Küçük raporlarda fark edilmez, milyon satırlık log üretiminde belirleyicidir.
Ham metin ve kaçış dizileri
"\n" satır sonu, "\t" sekme, "\\" ters eğik çizgidir. Windows dosya yolları ve düzenli ifadelerde ters eğik çizgi çok geçtiği için önüne r konmuş ham metin (raw string) kullanılır: r"C:\raporlar\yeni". Regex dersinde buna sık sık ihtiyaç duyacaksın.