
核心是把字符串里的占位符(比如 {name}、{age:02d})识别出来,再用实际值替换。关键不在拼接,而在解析规则、支持类型转换和安全回退。
识别并提取占位符
用正则匹配常见格式,如 {key} 或 {key:format_spec}。Python 可用 re.findall(r'\{([^}]+)\}', s) 提取所有花括号内内容;更完整需支持嵌套转义(如双大括号 {{ 表示字面量),此时建议复用标准库的 string.Formatter 解析逻辑,或参考其 parse() 方法返回的 token 序列。
支持格式说明符(format spec)
占位符中冒号后的内容(如 {price:.2f} 中的 .2f)需交由对应类型处理:数值走 format(value, spec),字符串可支持 s、!r、!s 等转换标记。注意不是所有 spec 都通用——对字符串用 :05d 应静默忽略或报错,而非强转引发异常。
- 解析时拆出
key、conversion(!r等)、format_spec三部分 - 获取值后,先按 conversion 处理(如
!r → repr(val)),再对结果应用 format_spec - 若 format_spec 不适用当前类型,可跳过或抛出明确异常,避免隐式错误
提供默认值与缺失键处理
用户常需要“键不存在时显示空字符串”或“显示默认文案”。可在查找值时加一层封装:查不到就返回预设默认值,而非直接报 KeyError。例如:
- 允许调用时传入
defaults={'name': 'Anonymous'} - 在格式化器内部,用
mapping.get(key, defaults.get(key))获取值 - 支持占位符语法扩展,如
{name:-Unknown}表示“未定义时用 Unknown”,类似 Bash 参数展开
避免执行任意代码,保证安全性
不解析表达式(如 {user.name.upper()}),只做键查找+格式化。若需动态计算,应由调用方预先提供计算好的值,或显式启用沙箱函数白名单(非常规需求,一般不建议)。所有键名仅作字典查找,禁止 eval、getattr 链式调用或属性穿透,防止意外访问私有成员或触发副作用。
不复杂但容易忽略细节——尤其格式适配和缺失处理。做好这四点,就能稳稳支撑模板场景,又不失灵活性。











