在 python 插值中检测与命名占位符混合的 %s

发布于 2024-12-25 23:30:50 字数 387 浏览 3 评论 0原文

显然,Python 将允许

'%s %(var)s' % {'var': 'x'}

产生

"{'var': 'x'} x"

我正在编写的东西,我基本上只需要 python 的命名占位符替换功能。有什么方法可以检测命名占位符和位置占位符的混合吗?

编辑:这个的背景是我正在写一些类似模板工具的东西。在到处写了一堆带有 %(named)s 的东西之后,你可以调用 template.substitute(dict) 来替换所有内容。我试图防止人们在字符串中留下 %[srfd,etc] (因为他们忘记插入或其他东西),如果它被留在那里,则会抛出错误。

So apparently, Python will allow

'%s %(var)s' % {'var': 'x'}

which produces

"{'var': 'x'} x"

I'm writing something where I basically want python's named placeholder substitution features only. Is there any way to detect a mix of named and positional placeholders?

EDIT: The context of this is that I'm writing something that's sort of a templating tool. After writing a bunch of stuff with %(named)s all over the place, you then call template.substitute(dict) to go and replace everything. I'm trying to prevent the case where people leave %[srfd,etc] in the string(because they forgot to interpolate or something) by throwing an error if it's been left there.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

A君 2025-01-01 23:30:50

str.__mod__ 内置函数不可重新编程。没有办法有选择地关闭其某些功能。

但是,您可以使用正则表达式来定位位置占位符并在字符串插值之前转义它们:

>>> d = {'var': 'x'}
>>> template = '%s %(var)s'
>>> esc_template = re.sub(r'(%[^()]*[sdf])', r'%\1', template)
>>> esc_template % d
'%s x'

The str.__mod__ builtin function isn't reprogrammable. There isn't a way to selectively turn-off some of its features.

You could however use a regex to locate the positional placeholders and escape them prior to string interpolation:

>>> d = {'var': 'x'}
>>> template = '%s %(var)s'
>>> esc_template = re.sub(r'(%[^()]*[sdf])', r'%\1', template)
>>> esc_template % d
'%s x'
倾城花音 2025-01-01 23:30:50

如果 Raymond Hettinger 告诉你它是如何完成的,你会听,因为他是对的:)

另一种选择是子类 string.Template 定义您自己的替换逻辑和语法。

If Raymond Hettinger tells you how it's done, you listen, because he's right :)

Another option is to subclass string.Template to define your own substitution logic and syntax.

荒芜了季节 2025-01-01 23:30:50

不是即时修复选项,但为了扩展 agander 的评论,使用 str.format 至少可以保证您不会意外填写任何未命名的占位符而不会看到错误。这是因为它通过使用正确的方法调用语法将位置替换与命名替换分开:

>>> '%s %(var)s' % {'var': 'x'}
"{'var': 'x'} x"
>>> '{} {var}'.format(var='x')

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    '{} {var}'.format(var='x')
IndexError: tuple index out of range
>>> '{} {var}'.format(8, var='x')
'8 x'

我经常使用支持两种不同替换语法的Python有一个附带好处,尽管它有点滥用功能炎。由于我编写了大量代码来组装 SQL 查询以传递到数据库接口,该接口使用 %s 作为参数化查询的占位符,因此我使用 str 进行所有外层查询粘贴。 format,这使得 %s 占位符完全不受干扰,而不必不断地转义它们。

>>> '%s {var}'.format(var='x')
'%s x'

如果这就是您希望在输出中传递 %ss 的原因,那么 str.format 可以大大简化您的生活。

Not an instant-fix option, but to expand on agander's comment, using str.format does at least guarantee you don't accidentally fill in any non-named placeholders without seeing an error. This is because it separates out the positional substitutions from the named ones by using proper method call syntax:

>>> '%s %(var)s' % {'var': 'x'}
"{'var': 'x'} x"
>>> '{} {var}'.format(var='x')

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    '{} {var}'.format(var='x')
IndexError: tuple index out of range
>>> '{} {var}'.format(8, var='x')
'8 x'

There's a side benefit I use quite often to Python supporting two different substitution syntaxes, though it's a bit of abuse of featuritis. Since I write a lot of code that assembles SQL queries to pass to a DB interface, which uses %s for placeholders for parameterised queries, I do all my outer-level query pasting with str.format, which leaves the %s placeholders completely unmolested without having to continually escape them.

>>> '%s {var}'.format(var='x')
'%s x'

If that's the reason you have %ss that you expect to be passed through in your output, str.format could simplify your life a lot.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文