带有内联管道的Python string.format

时间:2016-01-27 00:06:30

标签: python

我为用户消息格式化了很多字符串。一个可能看起来像这样:

def sms(**kwargs):
  return "Sorry {name}, but your payment was rejects. Please visit {url} and try again.".format(
    name=kwargs.get('name'),
    url=shorten_url(kwargs.get('url'))
  )

如果我不需要重新格式化任何关键字args,我可以这样做,这很好:

def sms(**kwargs):
  return "Sorry {name}, but your payment was rejects. Please visit {url} and try again.".format(**kwargs)

所以我希望也许可以这样做:

def sms(**kwargs):
  return "Sorry {name}, but your payment was rejects. Please visit {url|shorten_url} and try again.".format(**kwargs)

所以我可以使用管道内联格式化字符串。这可能看起来不是什么大问题,但我写了很多这些消息。

我注意到了python string.vformat功能,但我不确定这是不是我正在寻找的东西。有什么想法吗?

3 个答案:

答案 0 :(得分:4)

如果您继承var list = document.All.Where(m => m.LocalName.ToUpper() == "P" && searchTerm.IsMatch((m.TextContent ?? "").ToUpper()));,则可以实际实现自定义转换功能。以下示例基于this post

string.Formatter

输出import string class Template(string.Formatter): def convert_field(self, value, conversion): if conversion == 'u': # has to be a single char return value[:3] # replace with your shorten_url function # otherwise call the default convert_field method return super(Template, self).convert_field(value, conversion) print(Template().format('{url!u}', url='SOME LONG URL'))

另一种选择是在将kwargs传递给格式之前修改kwargs:

SOM

修改

根据您要使用>>> def sms(**kwargs): ... kwargs['shorturl'] = shorten_url(kwargs['url']) ... print('test {shorturl}'.format(**kwargs)) 的事实,您可以使用类似

的内容
globals()

def bold(s): return "<strong>" + s + "</strong>" def span(s): return "<span>" + s + "</span>" class Template(string.Formatter): def get_field(self, name, args, kwargs): parts = name.split('|') # use first part as actual field name ('url' in this case) obj, used_key = super(Template, self).get_field(parts.pop(0), args, kwargs) for filter in parts: obj = globals()[filter](obj) # call remaining parts as filter functions return obj, used_key print(Template().format('{url|bold|span}', url='SOME LONG URL')) # Outputs: <span><strong>SOME LONG URL</strong></span> 字符似乎与字段名称一起传递,因此您可以根据需要(ab)使用它。我建议添加一些错误处理并检查函数的调用顺序是你所期望的。我也不确定使用|是个好主意,特别是如果您要处理不安全的格式字符串。

答案 1 :(得分:3)

管道,或更好的&#34;过滤器&#34;,未在Python stdlib模板中实现。

标准Python库提供各种格式选项(对齐,填充,数字) 格式化,但它肯定有一些限制。

许多模板包都支持自定义过滤器,其中一个是jinja2

from jinja2 import Environment


def dumb_shorten_url(url):
    # just shortening for fun, implement real shortening
    return url[6:]

env = Environment()
env.filters["shorten_url"] = dumb_shorten_url


templ = env.from_string("Sorry {{name}}, but your payment was rejects. "
                        "Please visit {{url|shorten_url}} and try again.")

kwargs = {"name": "James", "url": "http://acme.com/one/two"}

print templ.render(**kwargs)

jinja2提供了更多内容(从文件系统,目录,循环中读取的模板, 条件表达式,转义HTML ...),但上面的例子将证明,它适用于 &#34;管道&#34;

答案 2 :(得分:0)

所以这更符合我的目标:

import re

def bold(string):
  return "<strong>" + string + "</strong>"

def format(string, **kwargs):
  # using the global scope, we can pipe kwargs through functions!
  scope = globals()
  def replace(substr):
    pieces = substr.group()[1:-1].split("|")
    value = kwargs.get(pieces[0])
    if len(pieces) > 1:
      pipes = pieces[1:]
      for pipe in pipes:
        value = scope[pipe](value)
    return value
  return re.sub(r"\{\S+\}", replace, string)

format("Hello {name|bold}, {yo}", **{"name":"Joe Schmo", "yo":"gimme more"})

它有效,但整个globals()事关注我。如果我在另一个我想要使用的文件中的另一个范围中定义一个函数怎么办?