Skip to main content
 首页 » 编程设计

python之将其他项的值替换为子字符串

2025年05月04日21www_RR

在字典里

{'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}'}