在字典里
{'A':'x', 'B':'y', 'C':'{A}_foo', 'D':'bar_{B}'}
,你将如何执行替代生产
{'A':'x', 'B':'y', 'C':'x_foo', 'D':'bar_y'}
?没有像 'C':'{A}_foo', 'D':'oops_{C}' 这样的嵌套,没有递归。
(这是一个简化的例子。实际上,它需要在 pandas dataframe 中逐行发生)
请您参考如下方法:
只需使用 Python 字符串格式并展开 d1 字典作为参数:
d1={'A':'x', 'B':'y', 'C':'{A}_foo', 'D':'bar_{B}'}
d2={k:v.format(v,**d1) for k,v in d1.items()}
>>> d2
{'A': 'x', 'B': 'y', 'C': 'x_foo', 'D': 'bar_y'}
但是,这里可能存在关键错误。考虑:
>>> d1={'A':'x', 'B':'y', 'C':'{A}_foo', 'D':'bar_{B}', 'E':'no-key_{Z}'}
>>> d2={k:v.format(v,**d1) for k,v in d1.items()}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <dictcomp>
KeyError: 'Z'
如果你想优雅地处理键错误,你可以像这样子类化 Formatter:
import string
class PartialFormatter(string.Formatter):
def __init__(self, missing='~~', bad_fmt='!!'):
self.missing, self.bad_fmt=missing, bad_fmt
def get_field(self, field_name, args, kwargs):
# Handle a key not found
try:
val=super(PartialFormatter, self).get_field(field_name, args, kwargs)
# Python 3, 'super().get_field(field_name, args, kwargs)' works
except (KeyError, AttributeError):
val=None,field_name
return val
def format_field(self, value, spec):
# handle an invalid format
if value==None: return self.missing
try:
return super(PartialFormatter, self).format_field(value, spec)
except ValueError:
if self.bad_fmt is not None: return self.bad_fmt
else: raise
d1={'A':'x', 'B':'y', 'C':'{A}_foo', 'D':'bar_{B}', 'E':'no-key_{Z}'}
d2={}
fmt=PartialFormatter()
for k,v in d1.items():
if '{' in v:
d2[k]=fmt.format(v,**d1)
else:
d2[k]=v
然后你只是默默地得到~~而不是KeyError:
>>> d2
{'A': 'x', 'B': 'y', 'C': 'x_foo', 'D': 'bar_y', 'E': 'no-key_~~'}
可以修改成你想要的行为......
或者,也许更好,使用try/except:
d1={'A':'x', 'B':'y', 'C':'{A}_foo', 'D':'bar_{B}', 'E':'bad-fmt_{:B}', 'F':'no-key_{Z}'}
d2={}
for k,v in d1.items():
if '{' in v:
try:
d2[k]=v.format(v,**d1)
except (KeyError, ValueError):
d2[k]=v
else:
d2[k]=v
>>> d2
{'A': 'x', 'B': 'y', 'C': 'x_foo', 'D': 'bar_y', 'E': 'bad-fmt_{:B}', 'F': 'no-key_{Z}'}
