【发布时间】:2016-06-14 12:20:41
【问题描述】:
给定一个格式字符串字典, 我想做级联/递归字符串插值。
FOLDERS = dict(home="/home/user",
workspace="{home}/workspace",
app_project="{workspace}/{app_name}",
app_name="my_app")
我从这个实现开始:
def interpolate(attrs):
remain = [k for k, v in attrs.items() if "{" in v]
while remain:
for k in remain:
attrs[k] = attrs[k].format(**attrs)
remain = [k for k in remain if "{" in attrs[k]]
interpolate() 函数首先选择格式字符串。
然后,它会替换字符串,直到不再有格式字符串。
当我使用以下 Python 字典调用此函数时,我得到:
>>> import pprint
>>> pprint.pprint(FOLDERS)
{'app_name': 'my_app',
'app_project': '/home/user/workspace/my_app',
'home': '/home/user',
'workspace': '/home/user/workspace'}
结果没问题,但是这个实现没有检测到引用循环。
例如,下面的调用导致无限循环!
>>> interpolate({'home': '{home}'})
谁能给我一个更好的实现?
编辑:解决方案
我认为 Leon 的解决方案既好又简单,Serge Bellesta 也是。
我会这样实现:
def interpolate(attrs):
remain = [k for k, v in attrs.items() if "{" in v]
while remain:
for k in remain:
attrs[k] = attrs[k].format(**attrs)
fmt = '{' + k + '}'
if fmt in attrs[k]: # check for reference cycles
raise ValueError("Reference cycle found for '{k}'!".format(k=k))
remain = [k for k in remain if "{" in attrs[k]]
【问题讨论】:
-
“谁能给我一个更好的实现?” - 这不是 SO 的用途。您要解决的实际问题是什么——您真的会得到任何带有参考周期的输入吗?
-
“谁能给我一个更好的实现?” - 它只需要为给定的输入产生完全相同的结果吗?
-
事实上,我正在寻找一个通用的解决方案。示例仅用于说明。是的,如果定义文件夹的用户在(通常)配置文件中出错,我们可以有循环:
interpolate()函数应该找到它。
标签: python string-interpolation string-substitution