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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容

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