Python 字符串格式化之 printf-style

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

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

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

printf-style 有如下两种形式:

  • 第一种形式:<format string> % <datum> ,其中的 <format string> 只有一个参数,此处的 <datum> 必须是单个非元组(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
    
  • 第二种形式:<format string> % [<datum_1>,...,<datum_n>] ,其中的 <format string> 有 n 个参数, [<datum_1>,...,<datum_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
    

转换说明符

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

转换说明符的排列顺序:

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

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

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

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

    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值放置在对应的 <datum> 之前。如果 .precision 也使用了 * ,那么 <datum> 应位于 width 值和 .precision 值之后。

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

    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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,207评论 0 13
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,417评论 0 2
  • 一、Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计...
    子非鱼_t_阅读 4,263评论 1 44
  • 刚刚知道班级里两个男生过了大连海事的初试,两个司考c证都远没有拿到而考研只用两个月时间的准备的男生。我在想,是不是...
    依然井柏然阅读 169评论 0 0
  • 页面中有多个选项卡,采用面向对象的方式实现. 代码简洁,有效减少代码冗余,便于后期维护 大家可以在这个基础上根据需...
    bob_play阅读 1,148评论 0 7