其他解决方案具有以下一个或多个特征,但不适用于我的需要: * 不支持复合/嵌套名称 * 需要 python 3 * 不起作用 * 不控制分层默认名称丢失钥匙的情况
所以这里有一个解决这些问题的解决方案。请注意,此解决方案仅适用于文本名称,例如“{key}”或“{nested[key]}”。不确定它是否会起作用,例如“{foo:<2s}”。
这也不处理数组,但可以很容易地扩展到这样做。您还可以替换您自己的函数来输出您想要的缺失值的任何占位符结果。
使用示例:
my_data = {
'hi': 'there',
'abc': {
'def': 'ghi'
},
'level1': {
'level2': {
'level3': 'nested'
}
}
}
s = "{hi} there"
print FormatDict(my_data).format(s) # 'there there'
s = "{hi} there {abc[def]}"
print FormatDict(my_data).format(s) # 'there there ghi'
s = "{hix} there {abc[def]}"
print FormatDict(my_data).format(s) # '{hix} there ghi'
s = "{hix} there {abc[defx]}"
print FormatDict(my_data).format(s) # '{hix} there {abc[defx]}'
s = "{hi} there {level1[level2][level3]}"
print FormatDict(my_data).format(s) # 'there there nested'
s = "{hix} there {level1[level2][level3x]}"
print FormatDict(my_data).format(s) # '{hix} there {level1[level2][level3x]}'
这是代码:
import string
class FormatDict(dict):
def set_parent(self, parent):
self.parent = parent
def __init__(self, *args, **kwargs):
self.parent = None
self.last_get = ''
for arg in (args or []):
if isinstance(arg, dict):
for k in arg:
self.__setitem__(k, arg[k])
for k in (kwargs or {}):
self.__setitem__(k, kwargs[k])
def __getitem__(self, k):
self.last_get = k
try:
val = dict.__getitem__(self, k)
return val
except:
ancestry = [k]
x = self.parent
while x:
ancestry.append(x.last_get)
x = x.parent
ancestry.reverse()
return '{' + ancestry[0] + ''.join(['[' + x + ']' for x in ancestry[1:]]) + '}'
def __setitem__(self, k, v):
if isinstance(v, dict):
v = FormatDict(v)
v.set_parent(self)
dict.__setitem__(self, k, v)
def format(self, s):
return string.Formatter().vformat(s, (), self)