2 ポイント 投稿者 GN⁺ 2025-04-11 | 3件のコメント | WhatsAppで共有
  • PEP 750 は Python に新しい文字列リテラルである テンプレート文字列(t"..." を導入する
  • f-string を一般化した形で、Template 型を生成し、文字列と補間値を結合する前に処理できる機能を提供する
  • Web テンプレート、セキュリティ検査、DSL(Domain-Specific Language)などで有用に使える

他の PEP との関係

  • f-string は PEP 498 で導入され、PEP 701 で構文が拡張された
  • PEP 501 は汎用テンプレート文字列(i-string)を提案したが保留となった
  • 現在の PEP 750 は PEP 501 を単純化・一般化した形で、既存のアイデアを基に発展したもの

動機と必要性

  • f-string は簡単だが、補間値を事前に加工できないため、セキュリティ上の問題が発生する可能性がある
  • SQL インジェクションや XSS 攻撃などの脆弱性を招くおそれがある
  • テンプレート文字列を使うと、補間値を事前に加工して安全に利用できる

例:

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

テンプレート文字列の仕様

テンプレート文字列リテラル

  • 接頭辞 t または T を使って定義する
  • string.templatelib.Template 型として評価される
  • f-string に似た構文をサポートし、ネストも可能
  • r 接頭辞と組み合わせ可能(rt, tr
  • u, b 接頭辞とは組み合わせ不可
  • f-string とテンプレート文字列は混在して使用できない

Template 型

  • 不変型であり、次の属性を持つ:
    • strings: 文字列断片のタプル
    • interpolations: 補間値オブジェクトのタプル
    • values: 補間値そのものの値タプル
    • __iter__(): 文字列と補間値を順に返すイテレータ

Interpolation 型

  • value: 評価結果
  • expression: 元の補間式文字列
  • conversion: 変換方式(r, s, a または None)
  • format_spec: 書式文字列

例:

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

デバッグ指定子 =

  • t"{value=}"t"value={value!r}" として解釈される
  • 空白もそのまま保持される(t"{value = }""value = {value!r}"

テンプレート文字列の連結

  • + 演算子で Templatestr、または Template 同士を結合できる
  • 連結結果は常に Template
  • 暗黙的な文字列連結(t"Hello " t"World")も可能

テンプレート文字列の処理方法

例: 大文字・小文字処理関数

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

例: f-string と同じ処理の実装

  • f() 関数で f-string と同じ結果を生成できる

例: 構造化ロギング

  • テンプレート文字列を使うと、ログメッセージと構造化された値を同時に出力できる
  • StructuredMessage または logging.Formatter のサブクラスとして実装できる

例: HTML テンプレート処理

  • html() 関数は補間位置に応じて内容を適切に escape したり属性として処理したりする
  • ネストしたテンプレートもサポートする

高度な使用パターン

  • 構造的パターンマッチングの使用を推奨(match 文)
  • 静的文字列はキャッシュキーとして使え、効率的なメモ化が可能
  • AST などの中間表現にパースして処理できる
  • Lazy または Async 評価のために lambda, await を使える

テンプレート文字列と既存のフォーマット文字列の関係

  • 既存の .format() に近い形でテンプレート関数を定義できる
  • 外部文字列をパースして Template に変換する from_format() も可能

互換性、セキュリティ、学習

  • 旧バージョンの Python では構文エラーになる可能性がある
  • セキュリティ面ではテンプレート処理が安全性を高める
  • f-string に似た構文のため学習しやすい

なぜ新しいテンプレート方式なのか?

  • 既存の Jinja のようなテンプレートはユーザー定義向け、またはデザイナー向け
  • テンプレートを開発者が直接扱えるように、Python 言語レベルでのサポートが必要
  • 表現力や型チェックなどの利点を活用できる

例示パターンの整理

  • 構造的パターンマッチングと下位属性のマッチング
  • テンプレートを関数のように再利用
  • ネストしたテンプレートをサポート
  • Lazy/Async 評価をサポート
  • 静的/動的分離によるキャッシュ最適化

その他の設計上の考慮事項

  • テンプレートは文字列に変換されず、__str__() は未実装
  • string.templatelib モジュールで関連クラスを提供する
  • Template, Interpolation はオブジェクト同一性基準で比較される
  • == または < 演算はサポートしない

参照実装と例

却下されたアイデア

  • 任意の接頭辞の使用(my_tag"..."
  • すべての補間式の遅延評価
  • プロトコルとして実装
  • __eq__, __hash__ の再定義
  • 元の文字列の完全復元
  • Decoded 型の追加
  • バイナリテンプレート文字列のサポート
  • フォーマット種別("html", "sql" など)指定機能
  • 文字列連結の制限
  • 任意の変換子(!x)の許可

3件のコメント

 
carnoxen 2025-04-11

一番満足できるフォーマットは JS と Python くらいですね。他の言語はちょっと…。

 
kandk 2025-04-11

明確で、できればただ一つの明白な方法があるべきだ。(There should be one-- and preferably only one --obvious way to do it.)

 
GN⁺ 2025-04-11
Hacker Newsのコメント
  • さまざまな言語が文字列フォーマットをどう扱うかは興味深い

    • Java は f/t-strings を追加しようと取り組んでいるが、あらゆる問題を解決しようとする完璧主義のせいで苦戦している
    • Go の開発者たちはこの問題をほとんど検討せず、無視したように見える
    • Python はバランスの取れたアプローチを取り、新しい文字列フォーマット方法を議論し、適切な実装を選んで使っている
    • Python のアプローチには同意せざるを得ず、.format()、f-strings、t-strings を通じて価値を得ている
  • Nick Humrich は PEP 501 を書き直して t-strings を導入した著者の一人であり、この PEP が受け入れられたことをとても喜んでいる

    • 4年前から PEP 501 の作業を始めていた
  • 言語レベルの機能が価値あるものか確信できない

    • f-string を返す関数で同じ結果を得られる
    • インジェクション安全性が欲しいなら、タグ型と文字列を返すサニタイズ関数を使えばよい
    • 簡潔ではあるが、単一文字で即時実行と遅延実行を区別するのは Python に慣れていない人には読みにくさをもたらすかもしれない
  • f-strings は好きだが、評価を遅延できない問題がある

    • str.format を使わなければならない場合があり、不便だ
  • lit-html のメンテナとして、JavaScript のタグ付きテンプレートリテラルとの類似点が興味深い

    • Python の Template クラスが JavaScript のタグ関数と引数を分離するやり方は独特だ
    • 入れ子になったテンプレート構造では html() 関数が不要かもしれない
  • JavaScript のタグ付きテンプレートリテラルが HTML の自動エスケープや SQL のパラメータ化に役立つ点が、Python にも適用されそうで期待している

  • Python が PHP に変わっていくようだという意見

    • f-strings と t-strings が言語に複雑さを加えている
    • string.format が最適だと思っており、% も長く使われてきたのだから許容できる
    • 言語チームにはもっと重要なことに集中してほしい
  • 言語に新しいものを追加し続けることへの不満

    • 言語が委員会によって設計されたように感じられる
  • この PEP は C++ の P1819 に似ているという意見

  • PEP のコードがあまりにも冗長だという意見

    • Python は実行可能な疑似コードというより、過剰な不要さを表現しているように見える
    • Ruby のコードと比較すると Python のコードはより冗長だ