Python:更新具有占位符的字典字符串?

时间:2020-10-06 06:25:49

标签: python python-3.x string eval

请考虑以下字符串:"{'a': A, 'b': B, 'c': 10}"。现在,我想更新此“字符串”并添加新的密钥d,并说值20,因此结果将是"{'a': A, 'b': B, 'c': 10, 'd': 20}"

通常,您可以将字符串(evalliteral_eval)评估为字典,更新所需的方式,然后将其转换回字符串。但是在这种情况下,存在占位符,在进行评估时不会被识别。

什么是最好的更新方式,因此旧值保持不变,但“ dict-string”已正确更新?

4 个答案:

答案 0 :(得分:1)

对于可以正确解析字典的更健壮的解决方案,您可以将lib2to3.refactor.RefactoringTool子类化,使用lib2to3.fixer_base.BaseFix子类的修复程序来重构代码,该修复程序具有寻找{{1}的模式}节点,以及一种dictsetmaker方法,该方法用叶子节点扩展了transform列表,该叶子节点由将在dict中构成新键值对的令牌组成:

children

这将输出:

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指定一个新节点。

您可以在prefix模块的Grammar.txt中找到Python语法的定义。

演示:https://repl.it/@blhsing/RudeLimegreenConcentrate

答案 1 :(得分:0)

我认为您可以:

选项1-添加

在字符串末尾的“}”之前插入新的字符串“,key:value”。

选项2-RagEx用于添加/更新

1-使用find()并搜索密钥。如果存在,请使用正则表达式替换:

re.replace(regex_search,regex_replace,contents)

因此,使用类似的内容:

string = re.sub(r'key: (.+),', 'key: value', article)

2-如果find()失败,请使用选项1的加法

答案 2 :(得分:0)

如果只是要在字符串末尾添加...

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进行类似操作,以找到索引并改用该索引号。

基本上是重写整个字符串,但是字符串是不变的,我们该怎么办。

答案 3 :(得分:0)

这绝不是最好的解决方案,但这是一种方法:

FlyoutItem

输出:

@client.event
async def on_member_join(member):
    roles = {"Level": 705112591927869513, "Interests": 705116168444444773, "Region": 725984087948656710,
             "Subscriptions": 705122149152850062}
    
    member_role = discord.utils.get(member.guild.roles, name = "member")
    await member.add_roles(member_role)
    for role in roles.keys():
        newrole = discord.utils.get(member.guild.roles, id = roles[role])
        await member.add_roles(newrole)
    await member.send("Welcome to the server! Please read the rules and verify yourself to be able to type! "
"Link to jump directly to the message - link")
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}