gpt4 book ai didi

python - 在 Python 中使用转义进行递归字符串替换

转载 作者:太空宇宙 更新时间:2023-11-04 03:43:33 25 4
gpt4 key购买 nike

我用 Python 编写了一个简单的脚本来根据源目录结构生成一些项目。我在其中使用了 Formatter,因为事实证明它非常方便,可以使用字典(也嵌套!)替换字符串。

然而现在,在扩展脚本的同时,我需要一个更复杂的替代品。首先,我想让替换是递归的。替换字段的字符串可能需要自己格式化(使用相同的参数)。其次,我需要能够根据提供的函数转义最终字符串(目前唯一的用例是 re.escape 以转义正则表达式)。

我在 Python 中寻找内置的东西,但没有找到任何有用的东西。 Formatter(如提供的那样)显然不符合这些标准。


我的第一个尝试是使用一个简单的函数,例如:

def expand_vars(string, vars):
while True:
expanded = string.format(**vars)
if expanded == string:
break
string = expanded
return string

它只是不断调用 format 直到字符串中没有更多变化(这意味着所有字段都被替换)。

然而嵌入这里转义并不容易。我只需要转义替换值(不是整个 string)和最终值(在每次调用时转义会导致对字符串的某些部分进行多次转义)。

此函数的另一个问题是它可能会无意中创建不是字段的字段。当其中一个字段以字符串 {a 结尾,而另一个字段以 b} 结尾时,在下一次迭代中我们会得到意外的字段 {ab}。 (好吧,它可以被认为是一个功能,但在我的案例中我并不这么认为。)


另一种方法是继承 Formatter。我最终得到了类似的结果:

class RecursiveEscapingFormatter(Formatter):
def __init__(self, escape=None):
Formatter.__init__(self)
self.escape = escape

def get_field(self, field_name, args, kwargs):
obj, arg_used = super(RecursiveEscapingFormatter, self).get_field(field_name, args, kwargs)
if self.escape is None:
nonEscapingFormatter = self
else:
nonEscapingFormatter = copy.copy(self);
nonEscapingFormatter.escape = None
obj = nonEscapingFormatter.vformat(obj, args, kwargs)
return obj, arg_used

def convert_field(self, value, conversion):
result = super(RecursiveEscapingFormatter, self).convert_field(value, conversion)
if self.escape is not None:
result = self.escape(result)
return result

现在的问题是我无法确保正确调用 check_unused_args。我看不出有什么方法可以合理地(=不需要覆盖整个类)跟踪 get_field 中的递归调用使用的参数。我自己不需要它,但是制作一个合适的类(一个以后可以继承自……的类)需要正确处理 check_unused_args。如何做到这一点?


或者也许有更好的方法来解决这个问题(通过转义进行递归替换)?

最佳答案

我遇到了类似的问题,下面是我如何解决的。

from string import Formatter

class RecursivelySubstitutedDictionary:
def __init__(self, dictionary):
self.formatter = Formatter()
self.dictionary = dictionary
self.substituting = set([])

def __getitem__(self, key):
if(key in self.substituting):
raise ValueError("Cyclic reference. Key: %s." % key)
self.substituting.add(key)
unsubstitutedval = self.dictionary[key]
substitutedval = self.formatter.vformat(unsubstitutedval,[],self)
self.substituting.remove(key)
return substitutedval

示例用法

regulardict = {
'hi': 'hello {arg}',
'arg': '{arg_1}{arg_2}',
'arg_1': 'wo',
'arg_2': 'rld',
}

print RecursivelySubstitutedDictionary(regulardict)['hi']
# prints hello world



cyclicdict = {
'hi': 'hello {arg}',
'arg': '{hi}',
}

print RecursivelySubstitutedDictionary(cyclicdict)['hi']
# raises ValueError: Cyclic reference. Key: hi.

如果 __setitem__ 被调用,您还可以考虑缓存替代值并清除缓存。至少那是我在原始代码中所做的。

关于python - 在 Python 中使用转义进行递归字符串替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24986679/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com