python format格式化显示

内置的format() 函数和str.format() 方法把各个类型的格式化方式委托给相应的
.__format__(format_spec) 方法。format_spec 是格式说明符:它是:
1,format(my_obj, format_spec) 的第二个参数,或者
2,str.format() 方法的格式字符串,{} 里代换字段中冒号后面的部分

简单应用:
在这里插入图片描述
这个里面的0.4f0.2f,是格式说明符(format_spec)
代换字段中的 ‘rate’ 子串是字段名称,与格式说明符无关,但 是它决定把 .format() 的哪个参数传给代换字段。

格式说明符使用的表示法叫格式规范微语言,参考网址:(https://docs.python.org/zh-cn/3.6/library/string.html#)(建议细看)下面我也会做些总结。

格式字符串语法:
str.format() 方法和 Formatter 类共享相同的格式字符串语法(虽然对于 Formatter 来说,其子类可以定义它们自己的格式字符串语法)。 具体语法与 格式化字符串字面值 相似,但也存在区别。

格式字符串包含有以花括号 {} 括起来的 替换字段。 不在花括号之内的内容被视为字面文本,会不加修改地复制到输出中。 如果你需要在字面文本中包含花括号字符,可以通过重复来转义: {{ and }}。
一、 例子(如何在文本中添加{}):
在这里插入图片描述
二、替换字段的语法如下:

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
arg_name          ::=  [identifier | digit+]
attribute_name    ::=  identifier
element_index     ::=  digit+ | index_string
index_string      ::=  <any source character except "]"> +

conversion        ::=  "r" | "s" | "a"

format_spec       ::=  <described in the next section>

用不太正式的术语来描述,替换字段开头可以用一个 field_name 指定要对值进行格式化并取代替换字符被插入到输出结果的对象。 field_name 之后有可选的 conversion 字段,它是一个感叹号 ‘!’ 加一个 format_spec,并以一个冒号 ‘:’ 打头。 这些指明了替换值的非默认格式。

field_name 本身以一个数字或关键字 arg_name 打头。 如果为数字,则它指向一个位置参数,而如果为关键字,则它指向一个命名关键字参数。 如果格式字符串中的数字 arg_names 为 0, 1, 2, … 的序列,它们可以全部省略(而非部分省略),数字 0, 1, 2, … 将会按顺序自动插入。 由于 arg_name 不使用引号分隔,因此无法在格式字符串中指定任意的字典键 (例如字符串 '10'':-]')。 arg_name 之后可以带上任意数量的索引属性表达式'.name' 形式的表达式会使用 getattr() 选择命名属性,而 '[index]' 形式的表达式会使用 __getitem__() 执行索引查找。

field_name
例子(数字和可以省略的):

位置参数说明符对于 str.format() 可以省略,因此 ‘{} {}’.format(a, b) 等价于 ‘{0} {1}’.format(a, b)。
在这里插入图片描述
在这里插入图片描述

例子(关键字)
在这里插入图片描述

例子(数量的索引属性表达式)
在这里插入图片描述
在这里插入图片描述

使用 conversion 字段在格式化之前进行类型强制转换。 通常,格式化值的工作由值本身的 __format__() 方法来完成。 但是,在某些情况下最好强制将类型格式化为一个字符串,覆盖其本身的格式化定义。 通过在调用 __format__() 之前将值转换为字符串,可以绕过正常的格式化逻辑。

conversion
目前支持的转换旗标有三种: '!s' 会对值调用 str()'!r' 调用 repr()'!a' 则调用 ascii()
在这里插入图片描述
在这里插入图片描述

格式规格迷你语言
format_spec
format_spec 字段还可以在其内部包含嵌套的替换字段。 这些嵌套的替换字段可能包括字段名称、转换旗标和格式规格描述,但是不再允许更深层的嵌套。 format_spec 内部的替换字段会在解读 format_spec 字符串之前先被解读。 这将允许动态地指定特定值的格式。

“格式规格”在格式字符串所包含的替换字段内部使用,用于定义单个值应如何呈现 (参见 格式字符串语法 和 格式化字符串字面值)。 它们也可以被直接传给内置的 format() 函数。 每种可格式化的类型都可以自行定义如何对格式规格进行解读。

大多数内置类型都为格式规格实现了下列选项,不过某些格式化选项只被数值类型所支持。

一般约定空格式字符串 ("") 将产生与对值调用 str() 相同的结果。 非空格式字符串通常会修改这一结果。

标准格式说明符 的一般形式如下:

format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
fill            ::=  <any character>
align           ::=  "<" | ">" | "=" | "^"
sign            ::=  "+" | "-" | " "
width           ::=  digit+
grouping_option ::=  "_" | ","
precision       ::=  digit+
type            ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

如果指定了一个有效的 align 值,则可以在该值前面加一个 fill 字符,它可以为任意字符,如果省略则默认为空格符。 在 格式化字符串字面值 或在使用 str.format() 方法时是无法使用花括号字面值 (“{” or “}”) 作为 fill 字符的。 但是,通过嵌套替换字段插入花括号则是可以的。 这个限制不会影响 format() 函数。

各种对齐选项的含义如下:

'<' 	强制字段在可用空间内左对齐(这是大多数对象的默认值)。

'>' 	强制字段在可用空间内右对齐(这是数字的默认值)。

'=' 	强制将填充放置在符号(如果有)之后但在数字之前。这用于以“+000000120”形式打印字段。此对齐选项仅对数字类型有效。当‘0’紧接在字段宽度之前时,它成为默认值。

'^' 	强制字段在可用空间内居中。

请注意,除非定义了最小字段宽度,否则字段宽度将始终与填充它的数据大小相同,因此在这种情况下,对齐选项没有意义。

sign 选项仅对数字类型有效,可以是以下之一:
在这里插入图片描述
'#' 选项可以让“替代形式”被用于转换。 替代形式可针对不同类型分别定义。 此选项仅对整数、浮点、复数和 Decimal 类型有效。 对于整数类型,当使用二进制、八进制或十六进制输出时,此选项会为输出值添加相应的 ‘0b’, ‘0o’ 或 ‘0x’ 前缀。 对于浮点数、复数和 Decimal 类型,替代形式会使得转换结果总是包含小数点符号,即使其不带小数。 通常只有在带有小数的情况下,此类转换的结果中才会出现小数点符号。 此外,对于 ‘g’ 和 ‘G’ 转换,末尾的零不会从结果中被移除。

',' 选项表示使用逗号作为千位分隔符。 对于感应区域设置的分隔符,请改用 ‘n’ 整数表示类型。

在 3.1 版更改: 添加了 ‘,’ 选项 (另请参阅 PEP 378)。

'_' 选项表示对浮点表示类型和整数表示类型 ‘d’ 使用下划线作为千位分隔符。 对于整数表示类型 ‘b’, ‘o’, ‘x’ 和 ‘X’,将为每 4 个数位插入一个下划线。 对于其他表示类型指定此选项则将导致错误。

在 3.6 版更改: 添加了 ‘_’ 选项 (另请参阅 PEP 515)。

width 是一个定义最小字段宽度的十进制整数。 如果未指定,则字段宽度将由内容确定。

当未显式给出对齐方式时,在 width 字段前加一个零 (‘0’) 字段将为数字类型启用感知正负号的零填充。 这相当于设置 fill 字符为 ‘0’ 且 alignment 类型为 ‘=’。

precision 是一个十进制数字,表示对于以 ‘f’ and ‘F’ 格式化的浮点数值要在小数点后显示多少个数位,或者对于以 ‘g’ 或 ‘G’ 格式化的浮点数值要在小数点前后共显示多少个数位。 对于非数字类型,该字段表示最大字段大小 —— 换句话说就是要使用多少个来自字段内容的字符。 对于整数值则不允许使用 precision。

最后,type 确定了数据应如何呈现。

可用的字符串表示类型是:
在这里插入图片描述
可用的整数表示类型是:
在这里插入图片描述
在上述的表示类型之外,整数还可以通过下列的浮点表示类型来格式化 (除了 ‘n’ 和 None)。 当这样做时,会在格式化之前使用 float() 将整数转换为浮点数。

浮点数和小数值可用的表示类型有:
在这里插入图片描述
对齐文本以及指定宽度:
在这里插入图片描述
替代 %+f, %-f 和 % f 以及指定正负号:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
格式规范微语言为一些内置类型提供了专用的表示代码。比如,b 和 x 分别表示二进制和 十六进制的 int 类型,f 表示小数形式的 float 类型,而 % 表示百分数形式:

>>> format(42, 'b')
 '101010' 
>>>> format(2/3, '.1%')
 '66.7%'

格式规范微语言是可扩展的,因为各个类可以自行决定如何解释 format_spec 参数。例如, datetime 模块中的类,它们的 __format__ 方法使用的格式代码与 strftime() 函数一样。 下面是内置的 format() 函数和 str.format() 方法的几个示例:

>>> from datetime import datetime 
>>>> now = datetime.now() 
>>>> format(now, '%H:%M:%S')
 '18:49:05'
  >>> "It's now {:%I:%M %p}".format(now)
   "It's now 06:49 PM"

如果类没有定义 __format__ 方法,从 object 继承的方法会返回 str(my_object)。我们为 Vector2d 类(自己定义的类)定义了 __str__ 方法,因此可以这样做:

from array import array
import math


class Vector2d:

    typecode = 'd'

    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)

    def __iter__(self):
        return (i for i in (self.x, self.y))

    def __repr__(self):
        class_name = type(self).__name__
        return '{}({!r}, {!r})'.format(class_name, *self)

    def __str__(self):
        return str(tuple(self))

    def __bytes__(self):
        return (bytes([ord(self.typecode)]) +
                bytes(array(self.typecode, self)))

    def __eq__(self, other):
        return tuple(self) == tuple(other)

    def __abs__(self):
        return math.hypot(self.x, self.y)

    def __bool__(self):
        return bool(abs(self))


if __name__ == '__main__':
    v1 = Vector2d(3, 4)
    print(format(v1))

结果:
在这里插入图片描述
然而,如果传入格式说明符,object.__format__ 方法会抛出 TypeError:
在这里插入图片描述
我们将实现自己的微语言来解决这个问题。首先,假设用户提供的格式说明符是用于格式 化向量中各个浮点数分量的。我们想达到的效果是:

>>> v1 = Vector2d(3, 4) 
>>>> format(v1)
 '(3.0, 4.0)' 
>>>> format(v1, '.2f') 
'(3.00, 4.00)' 
>>> format(v1, '.3e')
 '(3.000e+00, 4.000e+00)'

实现这种输出的 __format__ 方法
在这里插入图片描述
下面要在微语言中添加一个自定义的格式代码:如果格式说明符以 ‘p’ 结尾,那么在极坐 标中显示向量,即 <r, θ >,其中 r 是模,θ(西塔)是弧度;其他部分(‘p’ 之前的部分) 像往常那样解释。

为自定义的格式代码选择字母时,我会避免使用其他类型用过的字母。在格 式规范微语言(https://docs.python.org/3/library/string.html#formatspec)中我 们看到,整数使用的代码有 ‘bcdoxXn’,浮点数使用的代码有 ‘eEfFgGn%’, 字符串使用的代码有 ‘s’。因此,我为极坐标选的代码是 ‘p’。各个类使用 自己的方式解释格式代码,在自定义的格式代码中重复使用代码字母不会出 错,但是可能会让用户困惑。

对极坐标来说,我们已经定义了计算模的 __abs__ 方法,因此还要定义一个简单的 angle 方法,使用 math.atan2() 函数计算角度。angle 方法的代码如下:

from array import array
import math


class Vector2d:

    typecode = 'd'

    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)

    def __iter__(self):
        return (i for i in (self.x, self.y))

    def __repr__(self):
        class_name = type(self).__name__
        return '{}({!r}, {!r})'.format(class_name, *self)

    def __str__(self):
        return str(tuple(self))

    def __bytes__(self):
        return (bytes([ord(self.typecode)]) +
                bytes(array(self.typecode, self)))

    def __eq__(self, other):
        return tuple(self) == tuple(other)

    def __abs__(self):
        return math.hypot(self.x, self.y)

    def __bool__(self):
        return bool(abs(self))

    # def __format__(self, fmt_spec=''):
    #     components = (format(c, fmt_spec) for c in self)
    #     return '({}, {})'.format(*components)

    def angle(self):
        return math.atan2(self.y, self.x)

    def __format__(self, fmt_spec=''):
        if fmt_spec.endswith('p'):
            fmt_spec = fmt_spec[:-1]
            coords = (abs(self), self.angle())
            outer_fmt = '<{}, {}>'
        else:
            coords = self
            outer_fmt = '({}, {})'
        components = (format(c, fmt_spec) for c in coords)
        return outer_fmt.format(*components)


if __name__ == '__main__':
    v1 = Vector2d(3, 4)
    # print(format(v1))
    print(format(v1, '.3f'))
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值