PEP 750 – Şablon dizeleri (t-strings) onaylandı
(peps.python.org)- 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
Templatetü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><script>alert('evil')</script></p>"
Şablon dizelerinin özellikleri
Şablon dizesi literal'i
tveyaTöneki kullanılarak tanımlanırstring.templatelib.Templatetü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'iconversion: dönüştürme yöntemi (r,s,aveya 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üyleTemplateilestrya da ikiTemplatebirleştirilebilir- Birleştirme sonucu her zaman
Templatetü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
StructuredMessageveyalogging.Formatteralt 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 (
matchifadesi) - 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,awaitkullanı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ürenfrom_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.templatelibmodülünde sunulur Template,Interpolationnesne kimliğine göre karşılaştırılır==veya<operatörleri desteklenmez
Referans uygulama ve örnekler
- CPython uygulaması
- Örnekler ve testler sunuluyor
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ı
Decodedtü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
En tatmin edici biçimlendirme bana göre sadece JS ve Python'da var. Diğer diller ise biraz...
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.)
Hacker News yorumu
Farklı dillerin string formatting konusunu ele alış biçimi ilginç
.format(), f-strings ve t-strings ile değer sağlıyorNick Humrich, PEP 501’i yeniden yazarak t-strings’i tanıtan yazarlardan biri ve bu PEP’in kabul edilmesinden çok memnun
Dil seviyesindeki bir özelliğin değerli olduğundan emin olmayanlar var
f-strings seviliyor, ancak değerlendirmeyi erteleyememeleri sorun yaratıyor
str.formatkullanmak gerekiyor ve bu rahatsız edicilit-html bakımcısı olarak JavaScript’in tagged template literals özelliğiyle benzerlikler ilgi çekici bulunuyor
Templatesınıfının JavaScript’teki tagged function ile argümanları ayırma biçimi kendine özgühtml()fonksiyonuna gerek kalmayabilirJavaScript’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
string.formaten iyi seçenek olarak görülüyor,%de uzun süredir kullanıldığı için kabul edilebilir bulunuyorDile sürekli yeni şeyler eklenmesinden rahatsız olanlar var
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