使用Python的时间也不短了,可是对字符串格式化的方式还是不怎么了解,尤其是对于自定义类型,如何实现友好的格式化输出?

printf-style的字符串格式化”%”号操作符的使用方法就不再赘述了,如果”%”后面不止一个参数,那么需要传入一个tuple,或者是一个dict。

由于”%”使用并不是那么方便,在非dict参数的情况下,tuple需要按照顺序组织,并且同一个参数不能够多次使用[1]。于是就提出了使用模板进行字符串格式化的方法[2]。这两种方法有在功能上有一定的重复,如何选择也全看个人喜好。

相对来说,模板格式化字符串功能更为强大和灵活,其语法可以参考[3],下面主要关注自定义类的格式化显示。

  • 在使用”%”操作符时,后面的转换字符代表的含义[4]:

    ‘r’ String (converts any Python object using repr()).
    ‘s’ String (converts any Python object using str()).
    ‘a’ String (converts any Python object using ascii()).

对应的,我们可以定义自定义类的__repr__()__str__() 来实现格式化输出(ascii()repr()一样调用__repr__(),但会对non-ASCII字符进行转义,结果形如\x, \u, \U等[5])。

  • 使用模板格式化时,我们除了可以使用内置的!s!r!a转换实现与上边相同的效果外,还可以通过定义类的__format__实现自定义格式化方法,这样就非常灵活了,线面通过例子来看一下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#coding:utf-8
class Test:

def __str__(self):
return 'in __str__()'

def __format__(self, format_spec):
if format_spec == 'own1':
return 'in __format__(), own1 method'
elif format_spec == 's':
return 'in __format__(), s method'
elif format_spec == 'h':
return 'in __format__(), h method'
else:
return 'in __format__(), default method'

def __repr__(self):
return 'in __repr__()'

if __name__ == '__main__':

test = Test()

print 'str(test) shows ' + str(test)
print 'repr(test) shows ' + repr(test)

print '\n-----------% format ----------'
print '%%s shows %s' % test
print '%%r shows %r' % test
# print '%%h shows %h' % test # will cause ValueError: incomplete format

print '\n---------template format --------'
print '{{}} shows {}'.format(test)
print '{{!r}} shows {!r}'.format(test)
print '{{!s}} shows {!s}'.format(test)

print '\n---------template use __format__() --------'
print '{{:s}} shows {:s}'.format(test) # use __format__ s conversion
print '{{:h}} shows {:h}'.format(test) # use __format__ h conversion
print '{{:own1}} shows {:own1}'.format(test) # use __format__ own1 conversion
print '{{:}} shows {:}'.format(test) # use __format__ default conversion

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
str(test) shows in __str__()
repr(test) shows in __repr__()

-----------% format ----------
%s shows in __str__()
%r shows in __repr__()

---------template format --------
{} shows in __format__(), default method
{!r} shows in __repr__()
{!s} shows in __str__()

---------template use __format__() --------
{:s} shows in __format__(), s method
{:h} shows in __format__(), h method
{:own1} shows in __format__(), own1 method
{:} shows in __format__(), default method

总结

如果只是实现简单的格式化,那么”%”和模板都可以实现,自定义类通过定义__str__()__repr__()来实现,但如果需要对一个类实现(多种)自定义转换的格式化,那么需要定义类的__format__()方法,并且只能通过使用模板来实现自定义转换的格式化。

参考

  1. [Python-3000] String formating operations in python 3k
  2. PEP 3101 – Advanced String Formatting
  3. string — Common string operations
  4. https://docs.python.org/3/library/stdtypes.html#string-formatting-operations
  5. Built-in Functions