我可以定义自己的格式规范吗?

时间:2017-10-08 16:48:47

标签: python python-2.7 format

我想定义自己的str.format()规范,例如

sed -i .bak -e 's/\(.*\)<animation id.*><animation>\(.*\)/\1\2/g; s/\(.*\)<\/animation><\/animation>\(.*\)/\1\2/g; s/\(.*\)<library_animations>\(.*\)/\1<library_animations><animation>\2/g; s/\(.*\)<\/library_animations>\(.*\)/\1<\/animation><\/library_animations>\2/g' Walk.dae

将被使用,例如,像这样:

def earmuffs(x):
    return "*"+str(x)+"*"

这样:

def triple2str(triple, fmt="g"):
    return "[{first:{fmt}} & {second:+{fmt}} | {third}]".format(
        first=triple[0], second=triple[1], third=triple[2], fmt=fmt)

到目前为止我能想出的最好的是

## this works:
>>> triple2str((1,-2,3))
'[1 & -2 | 3]'
>>> triple2str((10000,200000,"z"),fmt=",d")
'[10,000 & +200,000 | z]'

## this does NOT work (I get `ValueError: Invalid conversion specification`)
>>> triple2str(("a","b","z"),fmt=earmuffs)
'[*a* & *b* | z]'

的工作原理如下:

def triple2str(triple, fmt=str):
    return "[{first} & {second} | {third}]".format(
        first=fmt(triple[0]), second=fmt(triple[1]), third=triple[2])

这真的是我能做的最好吗? 我不满意的是,目前还不清楚如何合并修饰符(例如,上面的>>> triple2str((1,-2,3)) '[1 & -2 | 3]' >>> triple2str((10000,200000,"z"),fmt="{:,d}".format) '[10,000 & 200,000 | z]' # no `+` before `2`! >>> triple2str((10000,200000,"z"),fmt=earmuffs) '[*10000* & *200000* | z]' )。

+是否可扩展?

2 个答案:

答案 0 :(得分:1)

str.format本身不可扩展。但是,有两种方法:

1

使用自定义字符串格式化程序:https://docs.python.org/2/library/string.html#custom-string-formatting

重写format_field(obj, format_spec)方法以捕获可调用的format_spec。然后直接调用格式化程序。

此代码段可以为您提供帮助(至少可以使用py 3.5&amp; 2.7):

import string

class MyFormatter(string.Formatter):
    def __init__(self, *args, **kwargs):
        super(MyFormatter, self).__init__(*args, **kwargs)
        self.fns = {}

    def format_field(self, value, format_spec):
        # print(repr(value), repr(format_spec))

        # intercept {fmt} part with functions:
        if callable(value):
            result = super(MyFormatter, self).format_field(value, format_spec)
            self.fns[result] = value
            return result

        # intercept {var:{fmt}} with remembered {fmt}:
        if format_spec in self.fns:
            return self.fns[format_spec](value)
        else:
            return super(MyFormatter, self).format_field(value, format_spec)


def fn(val):
    return '*{}*'.format(val)


f = MyFormatter()
print(f.format("{var:{fmt}}", var=1000, fmt='g'))
print(f.format("{var:{fmt}}", var=1000, fmt=fn))

2

定义每对象格式方法__format__(self, format_spec),其中format_spec:之后的内容{var:g}。您可以根据需要格式化对象的自我呈现。

但是,在您的情况下,对象是ints / strs,而不是自定义对象,因此这种方法也没有多大帮助。

结论:

是的,你在问题中的解决方案是充分的,可能是最简单的。

答案 1 :(得分:1)

在python 3中,您可以调用f-strings中的函数,也许这可以提供帮助。

def earmuffs(val):
    return "*{}*".format(val)

form = lambda a: f"method {earmuffs(a[0])} and method {earmuffs(a[1])}"

b = ('one', 'two')

form(b)
>>>'method *one* and method *two*'
相关问题