2 poin oleh GN⁺ 2025-04-11 | 3 komentar | Bagikan ke WhatsApp
  • PEP 750 memperkenalkan literal string baru di Python, yaitu string templat (t"...")
  • Sebagai bentuk generalisasi dari f-string, ini menghasilkan tipe Template yang memungkinkan pemrosesan gabungan string dan nilai interpolasi sebelum dirender
  • Berguna untuk templat web, pemeriksaan keamanan, DSL (Domain-Specific Language), dan lainnya

Hubungan dengan PEP lain

  • f-string diperkenalkan melalui PEP 498, dan sintaksnya diperluas di PEP 701
  • PEP 501 sempat mengusulkan string templat umum (i-string), tetapi ditunda
  • PEP 750 saat ini merupakan bentuk yang disederhanakan dan digeneralisasi dari PEP 501, dikembangkan berdasarkan ide yang sudah ada

Motivasi dan kebutuhan

  • f-string memang sederhana, tetapi tidak bisa memproses nilai interpolasi sebelumnya, sehingga berpotensi menimbulkan masalah keamanan
  • Ada kekhawatiran memicu celah keamanan seperti SQL injection dan serangan XSS
  • Dengan string templat, nilai interpolasi bisa diproses lebih dulu agar aman digunakan

Contoh:

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

Spesifikasi string templat

Literal string templat

  • Didefinisikan dengan prefiks t atau T
  • Dievaluasi sebagai tipe string.templatelib.Template
  • Mendukung sintaks mirip f-string, termasuk nested
  • Bisa digabung dengan prefiks r (rt, tr)
  • Tidak bisa digabung dengan prefiks u atau b
  • f-string dan string templat tidak dapat dipakai campuran

Tipe Template

  • Merupakan tipe immutable dan memiliki properti berikut:
    • strings: tuple potongan string
    • interpolations: tuple objek nilai interpolasi
    • values: tuple nilai dari interpolasi
    • __iter__(): iterator yang mengembalikan string dan nilai interpolasi secara berurutan

Tipe Interpolation

  • value: hasil yang sudah dievaluasi
  • expression: string ekspresi interpolasi asli
  • conversion: cara konversi (r, s, a, atau None)
  • format_spec: string format

Contoh:

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

Penanda debug =

  • t"{value=}" ditafsirkan sebagai t"value={value!r}"
  • Spasi juga dipertahankan apa adanya (t"{value = }""value = {value!r}")

Penggabungan string templat

  • Operator + dapat digunakan untuk menggabungkan Template dengan str, atau Template dengan Template
  • Hasil penggabungan selalu bertipe Template
  • Penggabungan string implisit (t"Hello " t"World") juga dimungkinkan

Cara memproses string templat

Contoh: fungsi pemrosesan huruf besar

  • 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)

Contoh: implementasi pemrosesan yang sama seperti f-string

  • Fungsi f() dapat menghasilkan hasil yang sama seperti f-string

Contoh: structured logging

  • Dengan string templat, pesan log dan nilai terstruktur bisa dikeluarkan sekaligus
  • Bisa diimplementasikan dengan StructuredMessage atau subclass logging.Formatter

Contoh: pemrosesan templat HTML

  • Fungsi html() menangani konten dengan escape yang sesuai atau sebagai atribut, tergantung posisi interpolasi
  • Templat bertingkat juga didukung

Pola penggunaan lanjutan

  • Disarankan menggunakan structural pattern matching (pernyataan match)
  • String statis dapat dipakai sebagai cache key untuk memoization yang efisien
  • Bisa diparse dan diproses sebagai representasi perantara seperti AST
  • Untuk evaluasi lazy atau async, dapat menggunakan lambda dan await

Hubungan antara string templat dan string format yang sudah ada

  • Fungsi templat dapat didefinisikan dengan cara yang mirip .format() yang sudah ada
  • from_format() yang mem-parsing string eksternal dan mengubahnya menjadi Template juga dimungkinkan

Kompatibilitas, keamanan, dan pembelajaran

  • Pada Python versi lama, ini bisa memunculkan syntax error
  • Dari sisi keamanan, pemrosesan templat meningkatkan keselamatan
  • Karena sintaksnya mirip f-string, pembelajarannya relatif mudah

Mengapa pendekatan templat baru diperlukan?

  • Templat yang ada seperti Jinja ditujukan untuk pengguna kustom atau desainer
  • Diperlukan dukungan di level bahasa Python agar pengembang bisa menangani templat secara langsung
  • Keunggulan seperti daya ekspresif dan type checking dapat dimanfaatkan

Ringkasan pola contoh

  • Structural pattern matching dan pencocokan properti turunan
  • Menggunakan kembali templat seperti fungsi
  • Dukungan untuk templat bertingkat
  • Dukungan evaluasi lazy/async
  • Optimasi cache melalui pemisahan bagian statis/dinamis

Pertimbangan desain lainnya

  • Templat tidak diubah menjadi string, dan __str__() tidak diimplementasikan
  • Kelas terkait disediakan dalam modul string.templatelib
  • Template dan Interpolation dibandingkan berdasarkan identitas objek
  • Operasi == atau < tidak didukung

Implementasi referensi dan contoh

Ide yang ditolak

  • Menggunakan prefiks arbitrer (my_tag"...")
  • Evaluasi tertunda untuk semua ekspresi interpolasi
  • Implementasi berbasis protokol
  • Override __eq__ dan __hash__
  • Pemulihan penuh string asli
  • Menambahkan tipe Decoded
  • Dukungan string templat biner
  • Fitur penentuan jenis format ("html", "sql", dll.)
  • Pembatasan penggabungan string
  • Mengizinkan konverter arbitrer (!x)

3 komentar

 
carnoxen 2025-04-11

Formatting yang paling memuaskan menurut saya cuma ada di JavaScript dan Python. Bahasa lain agak...

 
kandk 2025-04-11

Akan ada satu cara yang jelas—dan sebaiknya hanya satu—untuk melakukannya. (There should be one-- and preferably only one --obvious way to do it.)

 
GN⁺ 2025-04-11
Komentar Hacker News
  • Menarik melihat bagaimana berbagai bahasa menangani pemformatan string

    • Java sedang berupaya menambahkan f/t-strings, tetapi mengalami kesulitan karena perfeksionisme yang ingin menyelesaikan semua masalah
    • Pengembang Go tampaknya hampir tidak mempertimbangkan masalah ini dan mengabaikannya
    • Python mengambil pendekatan yang seimbang dengan mendiskusikan metode pemformatan string baru dan memilih implementasi yang tepat untuk digunakan
    • Sulit untuk tidak setuju dengan pendekatan Python, dan ada nilai yang didapat dari .format(), f-strings, dan t-strings
  • Nick Humrich adalah salah satu penulis yang menulis ulang PEP 501 untuk memperkenalkan t-strings, dan sangat senang dengan diterimanya PEP ini

    • Mulai mengerjakan PEP 501 sejak 4 tahun lalu
  • Tidak yakin apakah fitur di tingkat bahasa memang bernilai

    • Hasil yang sama bisa diperoleh dengan fungsi yang mengembalikan f-string
    • Jika menginginkan keamanan terhadap injeksi, bisa memakai tipe tag dan fungsi sanitasi yang mengembalikan string
    • Memang ringkas, tetapi membedakan eksekusi langsung dan tertunda dengan satu karakter bisa membuatnya sulit dibaca bagi orang yang belum terbiasa dengan Python
  • Suka f-strings, tetapi ada masalah karena evaluasinya tidak bisa ditunda

    • Ada kalanya harus memakai str.format sehingga terasa merepotkan
  • Sebagai maintainer lit-html, menarik melihat kemiripannya dengan tagged template literal di JavaScript

    • Cara kelas Template di Python memisahkan fungsi tag dan argumen berbeda dari JavaScript cukup unik
    • Dalam struktur template bertingkat, fungsi html() mungkin tidak diperlukan
  • Ada harapan bahwa manfaat tagged template literal JavaScript untuk auto-escape HTML atau parameterisasi SQL juga akan berlaku di Python

  • Ada pendapat bahwa Python tampaknya berubah menjadi PHP

    • f-strings dan t-strings menambah kompleksitas pada bahasa
    • Menganggap string.format adalah yang paling optimal, dan % juga masih dapat diterima karena sudah lama digunakan
    • Berharap tim bahasa fokus pada hal yang lebih penting
  • Keluhan tentang terus ditambahkannya hal-hal baru ke dalam bahasa

    • Bahasanya terasa seperti dirancang oleh komite
  • Ada pendapat bahwa PEP ini mirip dengan P1819 di C++

  • Ada pendapat bahwa kode dalam PEP terlalu bertele-tele

    • Python terasa seperti mengekspresikan terlalu banyak hal yang tidak perlu, alih-alih pseudocode yang dapat dijalankan
    • Dibandingkan dengan kode Ruby, kode Python lebih bertele-tele