具代表性的面試主題

程式設計面試:如何用 Python 3.14 t-string 實作安全模板處理?

程式題困難
Offer.cc 編輯團隊發佈 更新

題幹

團隊升級到 Python 3.14,希望讓模板處理器在串接字串前檢查插值值。請解釋 t-string 產生什麼物件、如何遍歷片段,以及如何避免把模板 API 誤當成自動轉義。

題幹與適用場景

團隊升級到 Python 3.14,希望讓模板處理器在串接字串前檢查插值值。請解釋 t-string 產生什麼物件、如何遍歷片段,以及如何避免把模板 API 誤當成自動轉義。

PEP 750 為 Python 3.14 引入模板字串。t"..." 不會直接產生 str,而是產生 string.templatelib.Template,其中保留靜態字串片段與插值物件,應用程式可以在最後串接前執行驗證、轉義或領域轉換。

面試官考察點

重點包括:區分 f-string 的立即字串化與 t-string 的結構化結果、理解 TemplateInterpolation 欄位、處理原始值與格式說明、設計情境相關轉義、控制副作用,以及相容舊版 Python。

30 秒回答框架

「我會先強調 t-string 不是自動安全輸出。它把模板解析成靜態片段與插值物件,渲染器可以檢查原始值、表達式文字、轉換與格式說明,再依 SQL、HTML 或日誌情境執行專用編碼。模板本身不應執行任意字串串接;我會限制允許的值型別,測試巢狀模板、格式說明、例外與舊版回退,並把最終輸出當成不可信資料繼續驗證。」

分步驟深入解答

第一步:區分 f-string 與 t-string

f-string 會先求值並格式化成 str,中間結構不可恢復。t-string 使用 t 前綴,結果是 Template;靜態文字與插值仍分開,渲染器可在合併前檢查每一項。

第二步:理解核心物件

模板由字串片段與 Interpolation 組成。插值記錄值、表達式文字、轉換標記與格式說明,方便策略依來源或目標情境決定。不要假設遍歷結果就是已安全的最終字串。

第三步:寫出最小處理器

以下處理器只示範結構化遍歷,實際系統仍需依情境編碼:

python
from string.templatelib import Template

def render_plain(template: Template) -> str:
    parts = []
    for item in template:
        if isinstance(item, str):
            parts.append(item)
        else:
            parts.append(str(item.value))
    return "".join(parts)

message = t"Hello, {name}!"

str(item.value) 只適合沒有安全要求的純文字示例;SQL、HTML、Shell 與日誌必須使用各自的參數化或編碼 API。

第四步:處理轉換與格式說明

插值可能帶有 !s!r 或格式說明。渲染器應先決定是否允許轉換,再對轉換後的值套用目標情境編碼。不能把 repr 當作 HTML 轉義,也不能讓格式說明繞過型別白名單。

第五步:避免副作用表達式

t-string 仍會求值插值表達式來建立 Interpolation。模板處理器不能把 t-string 當成沙箱;若模板來源不可信,風險在模板建立階段已存在。對外掛或使用者輸入只接受資料佔位符,禁止動態執行表達式。

第六步:依輸出情境選擇策略

純文字可以依允許型別轉換;HTML 應使用經稽核的 HTML 轉義器;SQL 應使用驅動參數綁定;Shell 應避免串接並使用參數陣列;結構化日誌應傳遞欄位而非拼成一行。Template 提供結構,不取代這些安全邊界。

第七步:相容版本與 API 發現

Python 3.14 提供 string.templatelib。支援舊版時應透過版本適配選擇既有模板庫或明確降級為 f-string,不要假裝能在舊直譯器保留插值結構。啟動時檢查執行時版本,CI 覆蓋每個支援版本。

第八步:測試與觀測

測試靜態片段、巢狀 t-string、格式說明、例外、物件 __format__ 副作用與大型模板。記錄策略拒絕的值型別與模板來源,但不要把插值內容寫進可能公開的日誌;對輸出做情境專屬安全回歸。

設計取捨與邊界

結構化處理還是簡單串接

需要稽核、國際化或多種輸出目標時,保留結構能讓策略前移;一次性純文字腳本使用 f-string 更簡單。團隊應依風險與複用範圍選擇,不為所有字串引入模板管線。

彈性格式還是可預測型別

允許任意 __format__ 會提高表現力,也會引入副作用與型別漂移。公共渲染器應限制值型別、轉換與格式說明,並對拒絕給出可診斷錯誤。

模板物件還是最終字串

Template 適合在邊界內傳遞,最終輸出仍應在傳送、儲存或執行前再次依情境檢查。不要把 Template 當作已完成編碼的安全令牌。

失敗演練與演進計畫

HTML 轉義被繞過

讓插值實作自訂 __str__ 回傳帶標籤內容,確認純 str 轉換不會自動安全;改用情境編碼並加入惡意值回歸。

格式說明觸發例外

使用不支援的格式說明和物件 __format__ 拋錯,驗證處理器能定位具體插值並拒絕整次渲染,而不是回傳半截輸出。

舊直譯器誤執行

在 Python 3.13 啟動同一模組,確認版本檢查給出清晰錯誤或走明確相容實作,不能把語法錯誤留到生產。

常見誤區與追問

誤區一:認為 t-string 會自動轉義

追問:它解決了什麼?它保留結構,方便應用程式在串接前做策略處理;SQL、HTML 等安全仍由專用 API 負責。

誤區二:認為插值表達式不會執行

追問:何時求值?建立 t-string 時表達式會求值並記錄結果,因此不可信模板不能透過 t-string 取得沙箱能力。

誤區三:把 repr 當作安全編碼

追問:為什麼不行?repr 是除錯表示,不保證符合 HTML、SQL、Shell 或日誌欄位的編碼規則。

延伸追問與參考答案

t-string 適合取代所有 f-string 嗎?

不適合。只有需要在合併前檢查或轉換插值的邊界才有結構收益;普通純文字仍可使用 f-string。

如何為 SQL 設計渲染器?

不要生成 SQL 字串;把靜態片段與值映射到驅動的參數佔位符,值透過參數綁定傳遞,模板只描述語法結構。

如何處理舊版 Python?

啟動時檢查版本,在 3.14 使用 string.templatelib,舊版使用既有模板實作或明確不支援,並用同一組安全語意測試驗證差異。

公開來源

同類題目

相關面試工具

用 Screenshot 處理演算法題

截圖題目後,依序看約束、解法、程式碼、邊界條件和複雜度。

查看工具