15 ポイント 投稿者 GN⁺ 2025-04-22 | 2件のコメント | WhatsAppで共有
  • t文字列(t-strings) は、Python 3.14 で新たに導入される 安全で柔軟な文字列処理機能
  • 従来の f-string とは異なり、t-string は文字列ではなく Template オブジェクトを返すため、自動的に出力されず安全に処理できる
  • t-string は HTML、SQL などの動的入力を安全にエスケープできる構造を備えている
  • JavaScript の タグ付きテンプレート(tagged templates) に似た概念で、さまざまな変換や処理の拡張が可能
  • Python 開発ツールのエコシステムがこの機能を十分にサポートすれば、Web/セキュリティ中心の文字列処理方式に大きな変化をもたらし得る

Python の新機能: t文字列(Template Strings)

  • Python 3.14 から t"..." 構文で使う Template 文字列(t-strings) が公式機能として導入される
  • 従来の f-string とは異なり、t-string は即座に文字列ではなく string.templatelib.Template オブジェクトとして評価される
  • このオブジェクトは出力前に別途 加工プロセスが必要であり、この過程を通じて 動的な値の安全な処理と変換 が可能になる

なぜ f-string は危険になり得るのか?

  • f-string は即座に文字列として評価されるため、ユーザー入力を含むコードでは SQL InjectionXSS が発生する可能性がある
    • 例: f"<div>{user_input}</div>" → 攻撃コードが直接挿入される可能性がある
  • t-string はこの評価を遅延させ、明示的に加工しなければ使えない ようにする

t-string の使用例

  • HTML エスケープ処理の例:

    evil = "<script>alert('bad')</script>"  
    template = t"<p>{evil}</p>"  
    safe = html(template)  
    # safeは "<p>&lt;script&gt;alert('bad')&lt;/script&gt;</p>"  
    
  • 属性の自動挿入など、より複雑な処理も可能:

    attributes = {"src": "roquefort.jpg", "alt": "Yum"}  
    template = t"<img {attributes} />"  
    element = html(template)  
    # 結果: "<img src='roquefort.jpg' alt='Yum' />"  
    

構造と API

  • Template オブジェクトは .strings.values 属性を通じて元のテキストと代入値を分離して提供する

  • interpolations 属性を通じて !s:&gt;8 などのフォーマット詳細情報にまでアクセスできる

  • 巡回(iteration)によって、テキストと値が混在した状態も直接加工できる

  • 手動生成も可能:

    from string.templatelib import Template, Interpolation  
    template = Template(  
      "Hello ",  
      Interpolation(value="World", expression="name"),  
      "!"  
    )  
    

面白い例: Pig Latin 変換器

  • Template オブジェクトの内容を巡回しながら単語を Pig Latin に変換する例:

    def pig_latin(template: Template) -> str:  
        ...  
    name = "world"  
    template = t"Hello {name}!"  
    assert pig_latin(template) == "Hello orldway!"  
    

今後の発展方向

  • t-strings は Web/セキュリティ中心の文字列処理方式に 安全性と拡張性 をもたらし得る
  • blackruff、VS Code などの開発ツールが t-string のフォーマットやハイライトをサポートすることが期待される
  • JavaScript 開発者になじみのある tagged template 方式 に近く、さまざまなフレームワークでも活用の可能性が高い

開発者コミュニティとの協業

  • 本機能は、さまざまな Python コミュニティメンバーの参加と協業を通じて完成した
  • とくに Jim、Paul、Koudai、Lysandros、そして Guido などのキーパーソンとの交流が言及されている
  • PEP 750 とそのサンプルリポジトリは GitHub で確認できる

Python 3.14 の t文字列機能は、文字列の 安全性と拡張性 を同時に確保し、従来の f-string の限界を超える重要な飛躍である

2件のコメント

 
GN⁺ 2025-04-22
Hacker Newsの意見
  • 全体として、この機能はかなりクール。基本的には次のようなコードを

    db.execute("QUERY WHERE name = ?", (name,))
    

    次のように変えるもの

    db.execute(t"QUERY WHERE name = {name}")
    

    新しい言語機能の複雑さを受け入れるだけの価値がこのシンタックスシュガーにあるのか、という疑問はある。2つの理由から、このケースではあると思う

    • ライブラリ開発者が {} 展開を通じて好きなことをできるようにするのは良いことで、良いユースケースが生まれる可能性がある
    • 言語全体でテンプレート構文を一般化し、すべてのライブラリが同じ方法で問題を解決するようにするのは、おそらく良いこと
  • また、ツールのエコシステムが t-strings をサポートするよう適応してほしい。たとえば、black や ruff が t-string の内容を整形し、vscode が HTML や SQL のような一般的な種類の内容を色分け表示してくれるとよい

    • t-strings についてのこの見方はかなり奇妙。テンプレート文字列が有効な HTML や SQL に変換されるべきだと推論できる唯一の方法は、文字列の明白な構文に基づくことだが、それは場当たり的にしかできず、テンプレート文字列機能とは無関係
    • この機能の設計では、文字列自体にどの種類のコンテンツなのか、あるいは最終的に何へ変換されるのかを示す印はない。すべては変換関数によって処理される
    • ほかの人が付け加えているように、sql”select * from {table}” のようなものならそれを実現できたかもしれないが、テンプレート内のものが変換関数によって有効な SQL に変換される保証はない。t“give me {table} but only {columns}” が、テンプレート処理後に有効な SQL へ変換されることもあり得る
  • 次のようなすっきりした SQL 構文は使えるだろうか?

    city = 'London'
    min_age = 21
    # Find all users in London who are 21 or older:
    users = db.get(t'
      SELECT * FROM users
      WHERE city={city} AND age>{min_age}
    ')
    

    db.get() 関数がテンプレートを受け取れるなら、可能なはず。これまで見た SQL の使い方の中で最もきれいな方法になりそう

  • 個人的には、この機能は一般的な機能になるには特定の問題に寄りすぎているように思う。Python はどんどん大きくなっている。Python は学びやすくてシンプルかと聞かれたら、「基本はそうだけど、言語全体を学ぶのはそうではない」と言わざるを得ない

    • その点で Go は、ほとんどすべての機能を拒んでいるのが興味深い。正直、ジェネリクスが多くの複雑さを追加しているので、それだけの価値があるのか確信が持てない。言語を元の焦点に合わせ続けるという一般的な考え方は正しいと思う。C++ は、言語自体が始まった当初とほとんど似ていない極端な例だろう
  • 大きな議論 (414ポイント、10日前、324件のコメント) リンク

  • かなりクール。JS の機能を移植するなら、次は辞書のアンパック/分割代入も手に入るだろうか?

    • この機能はものすごく欲しい。JS に戻る主な理由なんだ
    >>> {a, b=45, c=None, **d} = {'a': 234, xzy: 32456}
    >>> print(a, b, c, d)
    234 45 None {'xyz': 32456}
    
  • 新しい x-string 機能が組み込みであるだけなのは「ごまかし」のように感じる。次のようなことができるならクールだろう

    from foo import bar
    bar"zoop"
    
  • 2025年の Zen of Python:

    There should be one-- and preferably only one --obvious way to do it.
    

    2025年の Python 文字列フォーマット:

    • t-strings
    • f-strings
    • %-operator
    • +-operator
    • str.format()
  • テンプレートに適用する関数が、f-string の変数にその関数を適用するのとどう違うのか理解できない。だから、次のようにする代わりに:

    evil = "<script>alert('bad')</script>"
    template = t"{evil}"
    safe = html(template)
    

    なぜ単にこうしないのか:

    evil = "<script>alert('bad')</script>"
    safe = f"{html(evil)}"
    

    あるいは f-string を作る前に。単にサニタイズ/文字列操作の部分を忘れないようにして、必ず通るよう強制するだけなのか?

  • こんにちは! この記事を書いた本人です :-)

    • 会話に少し遅れて来たし、HN でこの記事がトレンドになっているのを見て少し驚いたけれど、質問には喜んで答えるつもり。1日中、合間を見て参加するようにする