Python 字符串格式化之 printf-style

本文翻译自 printf-style String Formatting 官方文档
转载请注明出处:https://www.jianshu.com/u/5e6f798c903a

Note: printf-style 的格式化操作存在一些缺陷,会导致许多常见的错误(例如无法正确显示元组和字典)。
改用以下三种的字符串格式化方式,可避免这些错误。

  • formatted string literal
  • str.format() 接口
  • template strings

字符串对象拥有一个独特的内置运算符: % (modulo),使用效果类似于 C 语言中 sprintf() 函数。

printf-style 有如下两种形式:

  • 第一种形式: % ,其中的 只有一个参数,此处的 必须是单个非元组(non-tuple )对象。

    aList = [1, 2, 3]
    aDict = dict(a=1, b=2, c=3)
    aSingleTuple = (1,) # 可以是仅有一个元素的元组
    aTuple = (1, 2, 3)
    
    print("%s" % aList)
    print("%s" % aDict)
    print("%s" % aSingleTuple)
    # print("%s" % aTuple) 会抛出异常
    

    输出

    [1, 2, 3]
    {'a': 1, 'b': 2, 'c': 3}
    1
    
  • 第二种形式: % [,...,] ,其中的 有 n 个参数, [,...,] 必须是有 n 个元素的元组,或有 n 个键值对的映射对象(如字典)

    aTuple = (1, 2, 3)
    aDict = dict(a=1, b=2, c=3) # 映射对象
    
    print("%s %s %s" % aTuple)
    print('%(language)s has %(number)03d quote types.' %
          {'language': "Python", "number": 2})
    print("%(a)s %(b)s %(c)s" % aDict)
    print("%s %s %s" % ("a", "b", "c"))
    # 不能直接给出参数,必须打包到数组中,如下代码会抛出异常
    # print("%s %s %s" % "a", "b", "c")
    

    输出

    1 2 3
    Python has 002 quote types.
    1 2 3
    a b c
    

转换说明符

中的参数被称作转换说明符(conversion specifier)。
转换说明符中至少包含两个字符,如 %s

转换说明符的排列顺序:

%[Mapping_key][Conversion_flags][Minimum_field_width][.Precision][Length_modifier][Conversion_type]

转换说明符中相关组件(components)的描述如下:

  1. % 标识转换说明符的起点

  2. mapping_key (可选),由带括号的字符序列组成,如 (somename) 。当 是字典(或其它映射类型)时,则必须使用 mapping_key ,并用 mapping_key 表示字典中相应的 key (这种情况下,转换说明符中不会出现 * ,因为 * 需要 是序列类型)。

    aDict = dict(a=1, b=2, c=3)
    print("%(b)s %(a)s " % aDict) # 不必使用所有key,顺序也可以变化
    print('%(language)s has %(number)03d quote types.' %
          {'language': "Python", "number": 2})
    # 输出:2 1
    # 输出:Python has 002 quote types.
    
  3. Conversion_flags (可选),会影响某些装换类型(conversion types)的结果。

  4. Minimum_field_width (可选)。如果将 Minimum_field_width 设置为 '*' (asterisk),那么需要将实际的width值放置在对应的 之前。如果 .precision 也使用了 * ,那么 应位于 width 值和 .precision 值之后。

    print("%*s,%*s,%s" % (4, "a", 4, "b", "c"))
    # 输出:   a    b c
    
  5. .Precision (可选),精度值跟在 .(dot) 之后。如果将.Precision 设置为 '*' (asterisk),那么需要将实际的精度值放置在对应的 之前。

    import math
    print("%.*f" % (2, math.pi))
    # 输出:3.14
    
  6. Length_modifier (可选)

  7. Conversion_type

Conversion_flags

Conversion_flags 字符含义如下:

Flag Meaning
'#' 使用替代形式(alternate form) 显示转换后的内容,在本节的Notes中会详细阐述
'0' 在数值左侧使用 0 进行填充,而不是默认的空格。
'-' 将转换后的内容在给定的字段宽度内左对齐,默认是右对齐(如果 '-''0' 同时存在,'-' 会覆盖 '0' )。如果转换后的内容大于给定的字段宽度,则不进行对齐。
' ' 在正数前插入一个空格
'+' 在正数前插入 '+' (会覆盖 ' ' 标记),负数会默认显示负号
>>> import math
# '0' 演示
>>> "%06.2f" % math.pi
'003.14'
# ‘-’ 演示
>>> "%-6s" % "Hi!"
'Hi!   '
>>> "%-06.2f" % math.pi
'3.14  '

Length_modifier

虽然可以添加 length 修饰符 (h, l, 或 L) ,但该修饰符会被 Python 忽略。
原因是 Python 并不需要该修饰符,所以在 Python 中 %ld%d 完全等价。

Conversion_type

Conversion_type 字符含义如下

Conversion Meaning Notes
'd' 有符号十进制整数
'i' 有符号十进制整数
'o' 有符号八进制整数 (1)
'u' 废弃的类型,含义与 'd' 相同 (6)
'x' 有符号十六进制数(小写) (2)
'X' 有符号十六进制数(大写) (2)
'e' 指数格式的浮点数(小写) (3)
'E' 指数格式的浮点数(大写) (3)
'f' 小数格式的浮点数 (3)
'F' 小数格式的浮点数 (3)
'g' 浮点格式。如果指数小于 -4 或大于等于精度时,会采用 'e' 格式;否则采用小数格式的浮点数。 (4)
'G' 浮点格式。如果指数小于 -4 或大于等于精度时,会采用 'E' 格式;否则采用小数格式的浮点数。 (4)
'c' 单个字符(接受整数,或仅包含单个字符的字符串)
'r' String (使用 repr() 函数转换相应的 Python 对象). (5)
's' String (使用 str() 函数转换相应的Python 对象). (5)
'a' String (使用 ascii()函数转换相应的Python 对象). (5)
'%' 不进行转换,会直接得到 '%'

关于 'g' 的示例:

# 格式化的默认精度是6位小数,所以当整数部分的长度大于等于7时,
# 便会采用指数形式
print("%g" % 1234567)
print("%.2g" % 1234) 
# 指数小于-4,也会采用指数形式
print("%g" % 0.000023456789)

输出

1.23457e+06
1.2e+03
2.34568e-05

Notes

  1. 如果使用替代形式(alternate form) ,也就是 '#' 标识,会在第一个数字前插入八进制标识符 ('0o')

  2. 如果使用替代形式(alternate form) ,也就是 '#' 标识,会在第一个数字前插入十六进制标识符 ( '0x' or '0X' )

  3. 如果使用替代形式(alternate form) ,也就是 '#' 标识,会导致结果始终包含小数点,即使小数点后没有数字。
    精度(precision)用于确定小数点后的有效位数,默认是 6 位小数。

    >>> "%#.0f" % 2
    '2.'
    >>> "%.0f" % 2
    '2'
    >>> "%#f" % 2
    '2.000000'
    >>> "%f" % 2
    '2.000000'
    
  4. 如果使用替代形式(alternate form) ,也就是 '#' 标识,会导致结果始终包含小数点,即使小数点后没有数字。
    精度(precision)用于确定小数点后的有效位数,默认是 6 位小数。

    >>> "%#.0g" % 0.00002
    '2.e-05'
    >>> "%.0g" % 0.00002
    '2e-05'
    >>> "%#g" % 0.00002
    '2.00000e-05'
    
  5. 如果精度(precision)值为 N ,则会截取结果的前 N 个字符。

    >>> "%.4s" % '1234567'
    '1234'
    >>> "%.4r" % '1234567'
    "'123"
    >>> "%.4a" % '1234567'
    "'123"
    
  6. 参考 PEP 237.

因为 Python 的字符串有明确的长度,因此 %s 转换不会假定字符串以 \0 结尾。

Changed in version 3.1:对绝对值超过 1e50 的值进行 %f 转换时,不会再将 %f 替换为 %g

你可能感兴趣的:(Python 字符串格式化之 printf-style)