2013-05-09 149 views
4

Python的安全字符串模板我有一个复杂的嵌套字典对象,e.g:嵌套字典对象

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这样的库。

+0

Python版本? – jamylak 2013-05-09 07:43:31

+0

是的,Python .... – Ayman 2013-05-09 07:49:00

+1

尽管我喜欢重新发明更好的车轮,但我还是有时间限制,并且喜欢使用已经测试过的东西:-) – Ayman 2013-05-09 08:04:47

回答

1

写你自己的格式化程序:

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=" 
+0

完美。正是我需要的!我正要写我自己的,但你的解决方案要好得多。 – Ayman 2013-05-09 09:34:58

+0

@Ayman - 如果有帮助,很高兴。另外请注意,这个实现不能被普遍使用,因为它不涉及参数例如... – root 2013-05-09 09:36:58

+0

这是我得到的,当我尝试这与Python 3.5 AttributeError:'str'对象没有属性'_formatter_field_name_split' 。任何解决方案 – bsuire 2016-04-14 13:20:44

1

要做到这一点的唯一方法是编写一个包装类,它实现字典和序​​列协议,将任何列表或字典返回值包装在同一个类中,并捕获任何KeyError或IndexError异常。

然后您的电话变成"…".format(**DefaultingWrapper(value))

+0

感谢您的建议。我尝试使用默认的dict实现,但失败,因为嵌套的dict不是这个新的默认dict类的子类。换句话说,这只会在最高层次上起作用。因此实现必须在模板级完成。 – Ayman 2013-05-09 09:12:27