如何将%s变成{0},{1}…不太笨拙?


11

我必须将包含占位符的字符串用于以后的替换,例如:

"A %s B %s"

并将其转换为:

"A {0} B {1}"

我想出了:

def _fix_substitution_parms(raw_message):
  rv = raw_message
  counter = 0
  while '%s' in rv:
    rv = rv.replace('%s', '{' + str(counter) + '}', 1)
    counter = counter + 1
return rv

那行得通,但感觉超级笨拙,根本不是“惯用的” python。

良好的惯用python解决方案会是什么样子?

更新说明:

  • 生成的字符串未在python中使用。我确实需要那里的柜台号码!(所以{}还不够好)!
  • 我只需要关心%s字符串,因为保证消息仅使用%s(什么也%i %f没有)

“ re.sub”可以用作替换功能,以带编号的花括号动态替换。顺便说一句:用{}代替数字也可以。
— 迈克尔·布彻

3
如果您有
— 可行的

@kojiro由于“太笨拙”
— 它对我不起作用

Answers:


5

我会按照Reznik 最初的建议去做,然后呼吁.format:

def _fix_substitution_parms(raw_message: str) -> str:
    num_to_replace = raw_message.count("%s")
    python_format_string_message = raw_message.replace("%s", "{{{}}}")
    final_message = python_format_string_message.format(*range(num_to_replace))
    return final_message

只有%s文本中有2个才可以使用 ?
— Charif DZ

@CharifDZ和Aran-Fey-查看编辑。你只是先数一下……
— 丹

看起来是一个很好的折衷方案……可读性强,但不太花哨。
— GhostCat向Monica C致敬。

8

re.sub与lambda函数一起使用,可以为每个元素重新应用一次替换,并itertools.count依次获取数字:

import itertools
import re

s = "A %s B %s"

counter = itertools.count()
result = re.sub('%s', lambda x: f'{{{next(counter)}}}', s)
print(result)  # 'A {0} B {1}'

请记住将其包装在一个函数中以多次执行此操作,因为您需要刷新itertools.count。


很好,尽管我觉得它有点“晦涩” ;-)
— GhostCat向Monica C致敬。19。/

@GhostCat并不是很模糊,当您调用next(counter)它产生下一个值时,counter是一个生成器,我总是忘了这个生成器的确不错的答案
— Charif DZ

@GhostCat正则表达式和函数式编程位于同一行:-PI猜测“模糊性”取决于您对这些工具的习惯程度。
— jfaccioni

3

我认为应该工作

rv.replace('%s','{{{}}}').format(*range(rv.count('%s')))


1
@GhostCat不要被一线人诱惑,请记住人们必须维护代码
— Dan

1
@丹我知道。但是我较少的代码也较少维护的代码。
— GhostCat向Monica C致敬。

这不少,调试起来也更困难,将来的开发人员也很难阅读。这个答案几乎与我的答案完全相同,它具有相同的函数调用(交换替换为split和join),但是如果中间步骤有问题怎么办?您将如何隔离它。新开发人员可以从代码中更快地了解其功能。我真的建议您不要将这么多的逻辑放在一行中。
— 丹

1
这不是一个好的班轮。X.join(Y.split(Z))只是一种令人费解的书写方式Y.replace(X, Z),并且不需要将range调用list(...)都包装在其中。
— 阿兰·费伊,

1
@Dan是的,对此表示抱歉,(仅现在一行):)
— Reznik

1

使用re.sub动态更换:

import re

text = "A %s B %s %s B %s"


def _fix_substitution_parms(raw_message):
    counter = 0
    def replace(_):
        nonlocal counter
        counter += 1
        return '{{{}}}'.format(counter - 1)
    return re.sub('%s', replace, raw_message)


print(_fix_substitution_parms(text))  # A {0} B {1} {2} B {3}

1
请记住,这不能解释转义的占位符(%%s)-如果您对此有所顾虑,可以改用正则表达式r'(?<!%)%s'。
— 阿兰·费伊

如果您允许一个愚蠢的问题:{{{}}}实际上是什么?
— GhostCat向Monica C致敬。

字符串格式化可以避免{我们\{像往常那样做{{。
— Charif DZ

1

使用生成器:

def split_and_insert(mystring):
    parts = iter(mystring.split('%s'))
    yield next(parts)
    for n, part in enumerate(parts):
        yield f'{{{n}}}'
        yield part

new_string = ''.join(split_and_insert("A %s B %s"))

-4

您尝试使用.format吗?

string.format(0 =值,1 =值)

所以:

"A {0} B {1}".format(0=value, 1=value)


1
这如何帮助任何人%s变成{}?
— 阿兰·费伊,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.