Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于嵌套dict对象的Python安全字符串模板_Python_Templates_String Formatting - Fatal编程技术网

用于嵌套dict对象的Python安全字符串模板

用于嵌套dict对象的Python安全字符串模板,python,templates,string-formatting,Python,Templates,String Formatting,我有一个复杂的嵌套dict对象,例如: value = { 'a': '100', bits: { 1: 'alpha', 2: 'beta', 3: ['31', '32', 901] } } 我需要使用模板“安全地”格式化它。这意味着如果找不到键,只需默默地忽略{}占位符。这些键可能不存在,我不想引发KeyErrors。问题是string.Template无法处理str.format所具有的相同功能。我使用的s

我有一个复杂的嵌套dict对象,例如:

value = { 
    'a': '100', 
    bits: {
        1: 'alpha', 
        2: 'beta', 
        3: ['31', '32', 901]
    }
}
我需要使用模板“安全地”格式化它。这意味着如果找不到键,只需默默地忽略
{}
占位符。这些键可能不存在,我不想引发KeyErrors。问题是string.Template无法处理str.format所具有的相同功能。我使用的str.format类似于:

"a=${a}, b1={bits[1]}, b31={bits[3]}, b9={bits[9]}".format(**value)
输出应为:

"a=100, b1=alpha, b31=(31, 32, 901), b9="
我不需要奇特的循环或if/else条件。只是简单的格式和子目录

我有什么选择?我更喜欢尽可能多地使用内置库或非常小的库


这不是一个web应用程序,因此如果可能的话,我不想为此而加载像jinja2这样的库。

唯一的方法是编写一个实现dict和序列协议的包装类,将任何列表或dict返回值包装在同一个类中,并捕获任何KeyError或IndexError异常


然后您的调用变成
“..”。format(**DefaultingWrapper(value))

编写您自己的格式化程序:

In [1]: from string import Formatter

In [2]: value = { 
   ...:     'a': '100', 
   ...:     'bits': {
   ...:         1: 'alpha', 
   ...:         2: 'beta', 
   ...:         3: ['31', '32', 901]}}

In [3]: class YourFormatter(Formatter):
   ...:     def get_value(self, field_name, args, kwargs):
   ...:         return kwargs.get(field_name, '')
   ...: 
   ...:     def get_field(self, field_name, args, kwargs):
   ...:         first, rest = field_name._formatter_field_name_split() 
   ...:         obj = self.get_value(first, args, kwargs) 
   ...:         
   ...:         for is_attr, i in rest:
   ...:             if is_attr:
   ...:                 obj = getattr(obj, i)
   ...:             else:
   ...:                 obj = obj.get(i, '')
   ...:         return obj, first
   ...:     


In [4]: fmt = YourFormatter()

In [5]: fmt.format("a={a}, b1={bits[1]}, b31={bits[3]}, b9={bits[9]}", **value)
Out[5]: "a=100, b1=alpha, b31=['31', '32', 901], b9="
对于Python3,您需要添加

import _string
并更换线路

first, rest = field_name._formatter_field_name_split() 


虽然我喜欢重新发明更好的轮子,但我有时间限制,更喜欢使用已经测试过的东西:-)谢谢你的建议。我尝试使用默认的dict实现,但失败了,因为嵌套的dict不是这个新的默认dict类的子类。换句话说,这只会在最高层起作用。因此,实现必须在模板级别完成。正是我需要的!“我正准备写我自己的,但你的解决方案要好得多。”艾曼——如果有帮助的话,我很高兴。还要注意的是,这个实现不能普遍使用,因为它不处理args,例如……这就是我在使用Python 3.5 AttributeError时得到的结果:“str”对象没有属性“\u formatter\u field\u name\u split”。有什么解决办法吗?我一直在考虑这个问题。更改在已编辑的解决方案中。您是否可以更改代码,使其也能够处理
位[3][2]
,以返回
901
?我有一个嵌套数据,我想分析它,看起来像这样:
{'id':'1','values':{'account':[{'text':'1200 Inventory','value':'115'}}}
first, rest = _string.formatter_field_name_split(field_name)