[英]substitute other items' values as substrings
In a dictionary在字典里
{'A':'x', 'B':'y', 'C':'{A}_foo', 'D':'bar_{B}'}
, how would you perform a substitution producing , 你将如何执行替代生产
{'A':'x', 'B':'y', 'C':'x_foo', 'D':'bar_y'}
? ? No nesting like
'C':'{A}_foo', 'D':'oops_{C}'
, no recursion.没有像
'C':'{A}_foo', 'D':'oops_{C}'
这样的嵌套,没有递归。
(This is a reduced example. In reality, it needs to happen row by row in a pandas dataframe) (这是一个简化的示例。实际上,它需要在 pandas 数据帧中逐行发生)
Just use Python string formatting and expand the d1
dict as the arguments:只需使用 Python 字符串格式并将
d1
字典扩展为 arguments:
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'}
However, there is a potential of key errors here.但是,这里可能会出现关键错误。 Consider:
考虑:
>>> 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'
If you want to gracefully handle key errors, you can subclass Formatter like so:如果你想优雅地处理关键错误,你可以像这样子类化 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
Then you just silently get ~~
instead of a KeyError
:然后你就默默地得到
~~
而不是KeyError
:
>>> d2
{'A': 'x', 'B': 'y', 'C': 'x_foo', 'D': 'bar_y', 'E': 'no-key_~~'}
Which can be modified to the behavior you desire...可以将其修改为您想要的行为...
Or, perhaps better still, use try / except
:或者,也许更好的是,使用
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}'}
With a list comprehension on d.items
, we can apply val.format(**d)
on each value to interpolate the values with the dict itself:通过对
d.items
的列表理解,我们可以对每个值应用val.format(**d)
以使用 dict 本身插入值:
>>> d = {'A':'x', 'B':'y', 'C':'{A}_foo', 'D':'bar_{B}'} >>> o = dict([ (key, val.format(**d)) for key,val in d.items() ]) >>> print (o) {'A': 'x', 'B': 'y', 'C': 'x_foo', 'D': 'bar_y'}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.