Python:是否更新具有占位符的dict字符串?
考虑以下字符串:Python:是否更新具有占位符的dict字符串?,python,python-3.x,string,eval,Python,Python 3.x,String,Eval,考虑以下字符串:“{'a':a,'b':b,'c':10}”。现在我想更新这个“字符串”并添加新的键d,比如说值20,所以结果将是“{'a':a,'b':b,'c':10,'d':20}” 通常,您可以将字符串(eval或literal\u eval)求值为dict,以您想要的方式更新并将其转换回字符串。但在本例中,有一些占位符,在计算时无法识别 更新它的最佳方法是什么,以便旧值保持不变,但“dict string”已正确更新?我认为您可以: 选项1-添加 在字符串末尾的“}”前面插入新字符串“
“{'a':a,'b':b,'c':10}”
。现在我想更新这个“字符串”并添加新的键d
,比如说值20
,所以结果将是“{'a':a,'b':b,'c':10,'d':20}”
通常,您可以将字符串(eval
或literal\u eval
)求值为dict,以您想要的方式更新并将其转换回字符串。但在本例中,有一些占位符,在计算时无法识别
更新它的最佳方法是什么,以便旧值保持不变,但“dict string”已正确更新?我认为您可以:
选项1-添加
在字符串末尾的“}”前面插入新字符串“key:value”
选项2-用于添加/更新的RagEx
1-使用find()
并搜索密钥。如果存在,则使用正则表达式替换:
re.replace(regex_search,regex_replace,contents)
因此,使用类似于:
string = re.sub(r'key: (.+),', 'key: value', article)
2-如果
find()
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)
为了获得正确解析dict的更健壮的解决方案,您可以使用子类lib2to3.refactor.RefactoringTool
来重构代码,该子类是lib2to3.fixer\u base.BaseFix
的子类,具有查找dictsetmaker
节点的模式,以及一种transform
方法,该方法使用叶节点扩展子项
列表,叶节点由将用于dict中新键值对的令牌组成:
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
是往返稳定的,因此在转换后保留所有空格,如果要在新节点之前插入空格,则应使用前缀指定新节点
您可以在lib2to3
模块的中找到Python语法的定义
演示:您为什么要使用字典的字符串表示法?有许多XML文件都有这种所谓的上下文(XML文件数据存储在数据库中),这是字典的字符串表示法。这样的上下文可以有占位符,这些占位符在某个点上被计算。我需要更新上下文以添加自定义密钥。如果不是placeholers,这将很容易,因为当时我不知道它们的值是什么,也不应该真正关心。这些占位符到底是什么?例如,active\u id
,是触发打开特定XML生成视图的另一条记录的id。这个ID是动态的,这意味着它可能会不同于它被打开的位置(在系统中)。因此,当需要计算上下文时,就知道要使用什么值,但我会在计算它之前进行更新(可以编写XML文件来更新其他特定的XML数据,但有很多这样的文件,所以我认为只需找到所有需要的内容并添加自定义数据(然后通过python完成)。您的问题不清楚。请在无法使用eval
的位置显示有问题的字符串。
{'a': A, 'b': B, 'c': 10, 'g': 2, 'h': 3}
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}