2 puan yazan GN⁺ 2025-04-11 | 3 yorum | WhatsApp'ta paylaş
  • PEP 750, Python'a yeni bir string literal olan şablon dizelerini (t"...") ekliyor
  • f-string'in genelleştirilmiş bir biçimi olarak, string ile eklenen değerleri birleştirmeden önce işlemeye imkân veren Template türünü sunuyor
  • Web şablonları, güvenlik kontrolleri ve DSL'ler (Domain-Specific Language) için yararlı şekilde kullanılabiliyor

Diğer PEP'lerle ilişkisi

  • f-string, PEP 498 ile tanıtıldı ve söz dizimi PEP 701 ile genişletildi
  • PEP 501 genel şablon dizelerini (i-string) önerdi ancak ertelendi
  • Güncel PEP 750, PEP 501'in sadeleştirilmiş ve genelleştirilmiş bir biçimi olarak mevcut fikirler üzerine geliştirildi

Motivasyon ve gereklilik

  • f-string basit olsa da, eklenen değerler önceden işlenemediği için güvenlik sorunları doğurabiliyor
  • SQL enjeksiyonu, XSS saldırıları gibi güvenlik açıklarına yol açma riski bulunuyor
  • Şablon dizeleri kullanıldığında, eklenen değerler önceden işlenerek güvenli biçimde kullanılabiliyor

Örnek:

  • evil = "<script>alert('evil')</script>"
  • template = t"<p>{evil}</p>"
  • assert html(template) == "<p>&lt;script&gt;alert('evil')&lt;/script&gt;</p>"

Şablon dizelerinin özellikleri

Şablon dizesi literal'i

  • t veya T öneki kullanılarak tanımlanır
  • string.templatelib.Template türü olarak değerlendirilir
  • f-string'e benzer söz dizimini destekler, iç içe kullanım da mümkündür
  • r önekiyle birlikte kullanılabilir (rt, tr)
  • u, b önekleriyle birlikte kullanılamaz
  • f-string ile şablon dizeleri karışık şekilde kullanılamaz

Template türü

  • Değiştirilemez bir türdür ve şu özelliklere sahiptir:
    • strings: string parçalarının tuple'ı
    • interpolations: eklenen değer nesnelerinin tuple'ı
    • values: eklenen değerlerin tuple'ı
    • __iter__(): string ile eklenen değerleri sırayla döndüren iterator

Interpolation türü

  • value: değerlendirilmiş sonuç
  • expression: özgün ekleme ifade string'i
  • conversion: dönüştürme yöntemi (r, s, a veya None)
  • format_spec: biçim string'i

Örnek:

  • name = "World"
  • template = t"Hello {name!r}"
  • assert template.interpolations[0].conversion == "r"

Debug belirteci =

  • t"{value=}", t"value={value!r}" olarak yorumlanır
  • Boşluklar da aynen korunur (t"{value = }""value = {value!r}")

Şablon dizelerinin birleştirilmesi

  • + operatörüyle Template ile str ya da iki Template birleştirilebilir
  • Birleştirme sonucu her zaman Template türüdür
  • Örtük string birleştirme de mümkündür (t"Hello " t"World")

Şablon dizelerini işleme yöntemi

Örnek: büyük/küçük harf işleme fonksiyonu

  • def lower_upper(template):
    • parts = []
    • for s in template:
      • if isinstance(s, str): parts.append(s.lower())
      • else: parts.append(str(s.value).upper())
    • return "".join(parts)

Örnek: f-string ile aynı işleme mantığının uygulanması

  • f() fonksiyonuyla f-string ile aynı sonuç üretilebilir

Örnek: yapılandırılmış loglama

  • Şablon dizeleri sayesinde log mesajı ile yapılandırılmış değerler aynı anda çıktı verilebilir
  • StructuredMessage veya logging.Formatter alt sınıfı olarak uygulanabilir

Örnek: HTML şablonu işleme

  • html() fonksiyonu, ekleme konumuna göre içeriği uygun şekilde escape eder veya öznitelik olarak işler
  • İç içe şablonları da destekler

İleri kullanım kalıpları

  • Yapısal pattern matching kullanımı önerilir (match ifadesi)
  • Statik string'ler cache anahtarı olarak kullanılabilir, verimli memoization mümkündür
  • AST gibi ara temsillere parse edilerek işlenebilir
  • Lazy veya Async değerlendirme için lambda, await kullanılabilir

Şablon dizeleri ile mevcut biçim dizeleri arasındaki ilişki

  • Mevcut .format()'a benzer şekilde şablon fonksiyonları tanımlanabilir
  • Harici string'leri parse ederek Template'e dönüştüren from_format() da mümkün

Uyumluluk, güvenlik, öğrenme

  • Eski Python sürümlerinde söz dizimi hatası oluşabilir
  • Güvenlik açısından şablon işleme güvenliği artırır
  • f-string'e benzer söz dizimi sayesinde öğrenmesi kolaydır

Neden yeni bir şablon yaklaşımı?

  • Jinja gibi mevcut şablonlar kullanıcı tanımlı ya da tasarımcılara yöneliktir
  • Şablonların geliştiriciler tarafından doğrudan ele alınabilmesi için Python dil düzeyinde destek gerekir
  • İfade gücü ve tür denetimi gibi avantajlardan yararlanılabilir

Örnek kalıpların özeti

  • Yapısal pattern matching ve alt özellik eşleştirmesi
  • Şablonların fonksiyon gibi yeniden kullanılması
  • İç içe şablon desteği
  • Lazy/Async değerlendirme desteği
  • Statik/dinamik ayrımıyla cache optimizasyonu

Diğer tasarım değerlendirmeleri

  • Şablonlar string'e dönüştürülmez, __str__() uygulanmamıştır
  • İlgili sınıflar string.templatelib modülünde sunulur
  • Template, Interpolation nesne kimliğine göre karşılaştırılır
  • == veya < operatörleri desteklenmez

Referans uygulama ve örnekler

Reddedilen fikirler

  • Rastgele önek kullanımı (my_tag"...")
  • Tüm ekleme ifadelerinin lazy değerlendirilmesi
  • Protokol olarak uygulanması
  • __eq__, __hash__ yeniden tanımlanması
  • Özgün string'in tamamen geri kazanılması
  • Decoded türünün eklenmesi
  • İkili şablon dizesi desteği
  • Biçim türü belirtme özelliği ("html", "sql" vb.)
  • String birleştirmeye kısıtlama getirilmesi
  • Rastgele dönüştürücülerin (!x) kabul edilmesi

3 yorum

 
carnoxen 2025-04-11

En tatmin edici biçimlendirme bana göre sadece JS ve Python'da var. Diğer diller ise biraz...

 
kandk 2025-04-11

Açık bir yöntem olacak; ve tercihen bunu yapmanın apaçık tek bir yolu. (There should be one-- and preferably only one --obvious way to do it.)

 
GN⁺ 2025-04-11
Hacker News yorumu
  • Farklı dillerin string formatting konusunu ele alış biçimi ilginç

    • Java, f/t-strings eklemeye çalışıyor ancak tüm sorunları çözmeye çalışan mükemmeliyetçilik yüzünden zorlanıyor
    • Go geliştiricileri ise bu konuyu neredeyse hiç dikkate almamış ve görmezden gelmiş gibi görünüyor
    • Python, dengeli bir yaklaşım benimseyerek yeni string formatting yöntemlerini tartışıyor ve uygun gördüğü uygulamayı seçip kullanıyor
    • Python’un yaklaşımına katılmamak zor; .format(), f-strings ve t-strings ile değer sağlıyor
  • Nick Humrich, PEP 501’i yeniden yazarak t-strings’i tanıtan yazarlardan biri ve bu PEP’in kabul edilmesinden çok memnun

    • PEP 501 üzerinde 4 yıl önce çalışmaya başlamış
  • Dil seviyesindeki bir özelliğin değerli olduğundan emin olmayanlar var

    • Aynı sonuç, f-string döndüren bir fonksiyonla elde edilebilir
    • Enjeksiyon güvenliği isteniyorsa etiket türü ve string döndüren bir arındırma fonksiyonu kullanılabilir
    • Kısa olsa da, tek bir harfle anında çalıştırma ile gecikmeli çalıştırmayı ayırmak Python’a aşina olmayanlar için okumayı zorlaştırabilir
  • f-strings seviliyor, ancak değerlendirmeyi erteleyememeleri sorun yaratıyor

    • Bu yüzden bazen str.format kullanmak gerekiyor ve bu rahatsız edici
  • lit-html bakımcısı olarak JavaScript’in tagged template literals özelliğiyle benzerlikler ilgi çekici bulunuyor

    • Python’daki Template sınıfının JavaScript’teki tagged function ile argümanları ayırma biçimi kendine özgü
    • İç içe geçmiş şablon yapılarında html() fonksiyonuna gerek kalmayabilir
  • JavaScript’teki tagged template literals’ın HTML otomatik escape veya SQL parametreleştirmesi için faydalı olması gibi, bunun Python’da da işe yarayacağı umuluyor

  • Python’un PHP’ye dönüşüyor gibi göründüğünü söyleyenler var

    • f-strings ve t-strings dile karmaşıklık ekliyor
    • string.format en iyi seçenek olarak görülüyor, % de uzun süredir kullanıldığı için kabul edilebilir bulunuyor
    • Dil ekibinin daha önemli şeylere odaklanması isteniyor
  • Dile sürekli yeni şeyler eklenmesinden rahatsız olanlar var

    • Dil, bir komite tarafından tasarlanmış gibi hissettiriyor
  • Bu PEP’in C++’taki P1819’a benzediğini söyleyen bir görüş var

  • PEP’teki kodun fazla ayrıntılı olduğu düşünülüyor

    • Python, çalıştırılabilir sözde kod olmaktan çıkıp gereğinden fazla fazlalık ifade ediyor gibi görünüyor
    • Ruby ile karşılaştırıldığında Python kodu daha ayrıntılı