Python: 更新有占位符的字典字符串?
Python: update dict string that has placeholders?
考虑这个字符串:"{'a': A, 'b': B, 'c': 10}"
。现在我想更新这个“字符串”并添加新键 d
假设值为 20
,所以结果将是 "{'a': A, 'b': B, 'c': 10, 'd': 20}"
通常,您可以将字符串(eval
或 literal_eval
)评估为字典,更新您想要的方式并将其转换回字符串。但是在这种情况下,有占位符,在评估时不会被识别。
更新它的最佳方法是什么,以便旧值保持不变,但“dict-string”已正确更新?
我认为你可以:
选项 1 - 添加
在字符串末尾“}”之前插入新字符串“, key: value”。
选项 2 - adding/updating
的 RagEx
1 - 使用 find()
并搜索密钥。如果存在,使用正则表达式替换:
re.replace(regex_search,regex_replace,contents)
所以使用类似的东西:
string = re.sub(r'key: (.+),', 'key: value', article)
2 - 如果 find()
失败,使用选项 1
的添加
如果只是在字符串末尾添加...
this_string = "{'a': A, 'b': B, 'c': 10}"
this_add = "'d': 20"
this_string = f"{this_string[:-1]}, {this_add}{this_string[-1]}"
print(this_string)
会输出
{'a': A, 'b': B, 'c': 10, 'd': 20}
如果您需要在中间插入新字符串,您可以使用 string.find 来定位索引并使用该索引号来做类似的事情。
它基本上是重写整个字符串,但是字符串是不可变的我们能做什么。
这绝不是最佳解决方案,但这是一种方法:
import re
dict_str = "{'a': A, 'b': B, 'c': 10}"
def update_dict(dict_str, **keyvals):
"""creates an updated dict_str
Parameters:
dict_str (str): current dict_str
**keyvals: variable amounts of key-values
Returns:
str:updated string
"""
new_entries = ", ".join(map(lambda keyval: f"'{keyval[0]}': {keyval[1]}", keyvals.items())) # create a string representation for each key-value and join by ','
return dict_str.replace("}", f", {new_entries}{'}'}") # update the dict_str by removing the last '}' and add the new entries
输出:
updated = update_dict(dict_str,
d = 20,
e = 30
)
print(updated)
{'a': A, 'b': B, 'c': 10, 'd': 20, 'e': 30}
some_dict = {
'g': 2,
'h': 3
}
updated = update_dict(dict_str,
**some_dict
)
print(updated)
{'a': A, 'b': B, 'c': 10, 'g': 2, 'h': 3}
为了获得正确解析 dict 的更强大的解决方案,您可以子类化 lib2to3.refactor.RefactoringTool
以使用作为 lib2to3.fixer_base.BaseFix
子类的修复器重构代码,其模式寻找 dictsetmaker
节点,以及一个 transform
方法,该方法扩展了 children
列表的叶节点,叶节点包含将在字典中构成新的 key-value 对的标记:
from lib2to3 import fixer_base, refactor, pytree
from lib2to3.pgen2 import token
class AddKeyValue(fixer_base.BaseFix):
PATTERN = "dictsetmaker"
def transform(self, node, results):
node.children.extend((
pytree.Leaf(token.COMMA, ','),
pytree.Leaf(token.STRING, "'d'", prefix=' '),
pytree.Leaf(token.COLON, ':'),
pytree.Leaf(token.NUMBER, 20, prefix=' ')
))
return node
class Refactor(refactor.RefactoringTool):
def __init__(self, fixers):
self._fixers= [cls(None, None) for cls in fixers]
super().__init__(None)
def get_fixers(self):
return self._fixers, []
s = "{'a': A, 'b': B, 'c': 10}"
print(Refactor([AddKeyValue]).refactor_string(s + '\n', ''))
这输出:
{'a': A, 'b': B, 'c': 10, 'd': 20}
lib2to3
是 round-trip 稳定的,因此在转换后保留所有空格,如果要在它之前插入空格,则应使用 prefix
指定新节点。
您可以在 lib2to3
模块的 Grammar.txt
中找到 Python 语法的定义。
考虑这个字符串:"{'a': A, 'b': B, 'c': 10}"
。现在我想更新这个“字符串”并添加新键 d
假设值为 20
,所以结果将是 "{'a': A, 'b': B, 'c': 10, 'd': 20}"
通常,您可以将字符串(eval
或 literal_eval
)评估为字典,更新您想要的方式并将其转换回字符串。但是在这种情况下,有占位符,在评估时不会被识别。
更新它的最佳方法是什么,以便旧值保持不变,但“dict-string”已正确更新?
我认为你可以:
选项 1 - 添加
在字符串末尾“}”之前插入新字符串“, key: value”。
选项 2 - adding/updating
的 RagEx1 - 使用 find()
并搜索密钥。如果存在,使用正则表达式替换:
re.replace(regex_search,regex_replace,contents)
所以使用类似的东西:
string = re.sub(r'key: (.+),', 'key: value', article)
2 - 如果 find()
失败,使用选项 1
如果只是在字符串末尾添加...
this_string = "{'a': A, 'b': B, 'c': 10}"
this_add = "'d': 20"
this_string = f"{this_string[:-1]}, {this_add}{this_string[-1]}"
print(this_string)
会输出
{'a': A, 'b': B, 'c': 10, 'd': 20}
如果您需要在中间插入新字符串,您可以使用 string.find 来定位索引并使用该索引号来做类似的事情。
它基本上是重写整个字符串,但是字符串是不可变的我们能做什么。
这绝不是最佳解决方案,但这是一种方法:
import re
dict_str = "{'a': A, 'b': B, 'c': 10}"
def update_dict(dict_str, **keyvals):
"""creates an updated dict_str
Parameters:
dict_str (str): current dict_str
**keyvals: variable amounts of key-values
Returns:
str:updated string
"""
new_entries = ", ".join(map(lambda keyval: f"'{keyval[0]}': {keyval[1]}", keyvals.items())) # create a string representation for each key-value and join by ','
return dict_str.replace("}", f", {new_entries}{'}'}") # update the dict_str by removing the last '}' and add the new entries
输出:
updated = update_dict(dict_str,
d = 20,
e = 30
)
print(updated)
{'a': A, 'b': B, 'c': 10, 'd': 20, 'e': 30}
some_dict = {
'g': 2,
'h': 3
}
updated = update_dict(dict_str,
**some_dict
)
print(updated)
{'a': A, 'b': B, 'c': 10, 'g': 2, 'h': 3}
为了获得正确解析 dict 的更强大的解决方案,您可以子类化 lib2to3.refactor.RefactoringTool
以使用作为 lib2to3.fixer_base.BaseFix
子类的修复器重构代码,其模式寻找 dictsetmaker
节点,以及一个 transform
方法,该方法扩展了 children
列表的叶节点,叶节点包含将在字典中构成新的 key-value 对的标记:
from lib2to3 import fixer_base, refactor, pytree
from lib2to3.pgen2 import token
class AddKeyValue(fixer_base.BaseFix):
PATTERN = "dictsetmaker"
def transform(self, node, results):
node.children.extend((
pytree.Leaf(token.COMMA, ','),
pytree.Leaf(token.STRING, "'d'", prefix=' '),
pytree.Leaf(token.COLON, ':'),
pytree.Leaf(token.NUMBER, 20, prefix=' ')
))
return node
class Refactor(refactor.RefactoringTool):
def __init__(self, fixers):
self._fixers= [cls(None, None) for cls in fixers]
super().__init__(None)
def get_fixers(self):
return self._fixers, []
s = "{'a': A, 'b': B, 'c': 10}"
print(Refactor([AddKeyValue]).refactor_string(s + '\n', ''))
这输出:
{'a': A, 'b': B, 'c': 10, 'd': 20}
lib2to3
是 round-trip 稳定的,因此在转换后保留所有空格,如果要在它之前插入空格,则应使用 prefix
指定新节点。
您可以在 lib2to3
模块的 Grammar.txt
中找到 Python 语法的定义。