使用自定义占位符的高级Python字符串格式化?

3
我可以帮您翻译,并使内容更加易于理解。如下是需要翻译的内容:

我有一个包含HTML模板的Python变量:

template = """
    <script>
        function work()
        {
            alert('bla');
        }
    </script>

    Success rate is {value:.2%} percent.
"""

我希望用一些适当的格式化小数替换{value:.2%}。由于我的模板可能包含大量JavaScript代码,我想避免使用{{}}转义花括号,因此直接使用template.format(...)不是一个选择。使用Template(template).substitute(...)也似乎不可能,因为我想要对value进行高级格式化。我可以将{value:.2%}替换为相应的%(value)...语法,然后使用template % ...。但我不喜欢这种语法,因为真实模板中的大多数变量都不需要高级格式化,所以我想保持占位符语法简单。那么我的问题是,是否可以在模板中使用自定义占位符,在必要时允许高级格式化,例如仅使用{{value}}[[value]],而不是所有出现在模板中的占位符都进行替换。为了实现我想要的效果,我可以首先使用正则表达式获取所有占位符,然后格式化它们的内容,最后在模板中进行替换。但我想知道是否有更简单的解决方案。最后,我想避免.format(...)在模板包含占位符时产生的错误,例如{{dont_want_this_substituted}},传递的字典中没有该值。

无法预先格式化您的值吗? - undefined
@CodyGuldner 我可以这么做,但我想在模板本身中指定格式。我可以使用正则表达式获取所有的占位符,然后通过首先对其内容进行格式化来替换它们,但我想知道是否存在更简单的解决方案。我将编辑问题以澄清这一点。 - undefined
为什么不使用多个文件呢?或者只是将模板单独存储。 - undefined
请参阅:自定义占位符语法 - undefined
2个回答

2

只需预处理您的模板。例如,如果您想要 [[...]] 作为模板标记,并保留单个的 { } 字符:

template = """
    <script>
        function work()
        {
            alert('bla');
        }
    </script>

    Success rate is [[value:.2%]] percent.
"""

result = template.replace("{", "{{").replace("}", "}}").replace("[[", "{").replace("]]", "}").format(value=0.8675309)

尝试使用不同数量的花括号来完成所有任务是很棘手的,因此我肯定会使用其他字符。但要小心,像[[]]这样的内容可能会在合法的JavaScript代码中出现。最好使用永远不会出现的其他字符。

谢谢,这确实是一个选项。不过,如果我想使用{{...}}作为占位符,可能会更加棘手,可能需要一些正则表达式替换。不知道是否有更好的方法呢?我还编辑了原始问题,要求只替换特定的占位符。 - undefined
在这种情况下,你会想要编写自己的模板引擎。 - undefined
1
  • 参见: https://dev59.com/KVsV5IYBdhLWcg3w-i0C#41231617 ;; 一个扩展str.format()方法的自定义类解决方案。
- undefined

0
忘掉正则表达式和预处理。你应该将模板分解,使变量部分不与<script>部分在同一个字符串中。
head = """
    <script>
        function work()
        {
            alert('bla');
        }
    </script>
"""


template = """
    {head}

    Success rate is {value:.2%} percent.
"""

最后,我想避免在模板中包含占位符(例如{{dont_want_this_substituted}}),但传递的字典中没有相应的值时,.format(...)会产生的错误。也就是说,我只想替换特定的占位符,而不是模板中出现的所有占位符。
这可能有点不太正规,但你可以使用collections.defaultdict,如这个回答所示。从那个回答中提取的代码示例(经过修改)。
from collections import defaultdict

my_csv = '{optional[first]},{optional[middle]},{optional[last]}'
print( my_csv.format( optional=defaultdict(str, first='John', last='Doe') ) )

我希望避免拆分模板,因为它来自一个文件。我将更新问题以澄清这一点。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接