python的常用三种格式化方法

最近看别人代码时,发现一个新的打印输出格式,很有意思,print(f’{}’),所以找了些资料学习总结了一下,现把几个常用的方法记录下来。

神奇的 % 号

% 号格式化字符串沿用的是C语言的方法,python官方也并未弃用%号,但也并不推荐这种格式化方式。

1
2
3
4
5
6
7
8
9
10
# 1、格式的字符串(即%s)与被格式化的字符串(即传入的值)必须按照位置一一对应
# ps:当需格式化的字符串过多时,位置极容易搞混
print('%s asked %s to do something' % ('egon', 'lili')) # egon asked lili to do something
print('%s asked %s to do something' % ('lili', 'egon')) # lili asked egon to do something

# 2、可以通过字典方式格式化,打破了位置带来的限制与困扰
print('我的名字是 %(name)s, 我的年龄是 %(age)s.' % {'name': 'egon', 'age': 18})

kwargs={'name': 'egon', 'age': 18}
print('我的名字是 %(name)s, 我的年龄是 %(age)s.' % kwargs)

str.format 内置函数方法

该format方法是在Python 2.6中引入的,是字符串类型的内置方法。因为str.format的方式在性能和使用的灵活性上都比%号更胜一筹,所以推荐使用

使用位置参数

1
2
3
# 按照位置一一对应
print('{} asked {} to do something'.format('egon', 'lili')) # egon asked lili to do something
print('{} asked {} to do something'.format('lili', 'egon')) # lili asked egon to do something

使用索引

1
2
# 使用索引取对应位置的值
print('{0}{0}{1}{0}'.format('x','y')) # xxyx

使用关键字参数or字典

1
2
3
4
5
# 可以通过关键字or字典方式的方式格式化,打破了位置带来的限制与困扰
print('我的名字是 {name}, 我的年龄是 {age}.'.format(age=18, name='egon'))

kwargs = {'name': 'egon', 'age': 18}
print('我的名字是 {name}, 我的年龄是 {age}.'.format(**kwargs)) # 使用**进行解包操作

填充与格式化

1
2
3
4
5
6
7
8
9
10
# 先取到值,然后在冒号后设定填充格式:[填充字符][对齐方式][宽度]

# *<10:左对齐,总共10个字符,不够的用*号填充
print('{0:*<10}'.format('开始执行')) # 开始执行******

# *>10:右对齐,总共10个字符,不够的用*号填充
print('{0:*>10}'.format('开始执行')) # ******开始执行

# *^10:居中显示,总共10个字符,不够的用*号填充
print('{0:*^10}'.format('开始执行')) # ***开始执行***

精度与进制

1
2
3
4
5
print('{salary:.3f}'.format(salary=1232132.12351))  #精确到小数点后3位,四舍五入,结果为:1232132.124
print('{0:b}'.format(123)) # 转成二进制,结果为:1111011
print('{0:o}'.format(9)) # 转成八进制,结果为:11
print('{0:x}'.format(15)) # 转成十六进制,结果为:f
print('{0:,}'.format(99812939393931)) # 千分位格式化,结果为:99,812,939,393,931

f-Strings 最近才学习到的方法。

str.format() 比 %格式化高级了一些,但是它还是有自己的缺陷。当需要传入的字符串过多时,仍然会显得非常冗长。与在Python 3.6中引入 了f-strings,不仅比str.format更简洁,性能上也更胜一筹

​ f-string是以f或F开头的字符串, 核心在于字符串中符号{}的使用。

{}中可以是变量名

1
2
3
4
name = 'egon'
age = 18
print(f'{name} {age}') # egon 18
print(F'{age} {name}') # 18 egon

{}中可以是表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 可以在{}中放置任意合法的Python表达式,会在运行时计算
# 比如:数学表达式
print(f'{3*3/2}') # 4.5

# 比如:函数的调用
def foo(n):
print('foo say hello')
return n

print(f'{foo(10)}') # 会调用foo(10),然后打印其返回值

# 比如:调用对象的方法
name='EGON'
print(f'{name.lower()}') # egon

在类中的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> class Person(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __str__(self):
... return f'{self.name}:{self.age}'
... def __repr__(self):
... return f'===>{self.name}:{self.age}<==='
...
>>>
>>> obj=Person('egon',18)
>>> print(obj) # 触发__str__
egon:18
>>> obj # 触发__repr__
===>egon:18<===
>>>
>>>
>>>
>>> # 在f-Strings中的使用
>>> f'{obj}' # 触发__str__
'egon:18'
>>> f'{obj!r}' # 触发__repr__
'===>egon:18<==='

多行f-Stings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 当格式化字符串过长时,如下列表info
name = 'Egon'
age = 18
gender = 'male'
hobbie1='play'
hobbie2='music'
hobbie3='read'
info = [f'名字:{name}年龄:{age}性别:{gender}',f'第一个爱好:{hobbie1}第二个爱好:{hobbie2}第三个爱好:{hobbie3}']

# 我们可以回车分隔到多行,注意每行前都有一个f
info = [
# 第一个元素
f'名字:{name}'
f'年龄:{age}'
f'性别:{gender}',

# 第二个元素
f'第一个爱好:{hobbie1}'
f'第二个爱好:{hobbie2}'
f'第三个爱好:{hobbie3}'
]

print(info)
# ['名字:Egon年龄:18性别:male', '第一个爱好:play第二个爱好:music第三个爱好:read']

引号的嵌套

1
2
3
4
5
6
# 当字符串嵌套发送冲突时,与正常的字符串处理方式是一样的
# 1、外层为单引号,内层嵌套也为单引号,并且想要输入的内容也为单引号,那么外层需要改用双引号
print("my name is 'egon'")

# 2、外层为单引号,内层嵌套也为单引号,并且想要输入的内容也为单引号,需要用到转义
print('my name is \'egon\'')

注意事项

1
2
3
4
5
#1、反斜杠可以用来进行字符转义,但不能用在{}的表达式中
f'{1\2}' # 语法错误

#2、注释#号也不能出现在{}的表达式中
f'{x#}' # 语法错误

括号的处理

基于3.5我们得知,不能在{}内出现反斜杠\,所以,当我们的输出的结果中需要包含{}时,下面的做法就是错误的

1
print(f'\{天王盖地虎\}')

类似于输出%号的做法

1
2
3
>>> print('%s%%' %30)
30%

若想输出{},那么需要在原有的基础上再套一层,如下

1
2
print(f'{{天王盖地虎}}') # {天王盖地虎}
print(f'{{{{天王盖地虎}}}}') # {{天王盖地虎}}

性能对比=>f_Stings性能最高

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
from timeit import timeit


def test_s():
name = 'Egon'
age = 18
return '%s:%s.' % (name, age)


def test_format():
name = 'Egon'
age = 18
return '{}:{}.'.format(name, age)


def test_f_strings():
name = 'Egon'
age = 18
return f'{name}:{age}.'


res1 = timeit(test_s, number=1000000)
res2 = timeit(test_format, number=1000000)
res3 = timeit(test_f_strings, number=1000000)
print(res1) # 0.3709844550030539
print(res2) # 0.47834375899401493
print(res3) # 0.3111891380031011, 最快

总结三种方式的应用场景

  • 如果使用的python3.6+版本的解释器,推荐使用f-Stings
  • 如果要兼容python2.x版本的python解释器,推荐使用str.format
  • 如果不是测试的代码,不推荐使用%

本文参考:详情地址