feat(docs): 添加多篇技术博客和竞赛文章

添加快速幂算法详解、蓝桥杯竞赛题解、Python字符串格式化指南等技术文章
新增多张封面图片并调整博客封面布局配置
This commit is contained in:
祀梦
2026-01-09 16:10:29 +08:00
parent a5fd8545f4
commit 13404a7430
7 changed files with 666 additions and 1 deletions

View File

@@ -0,0 +1,320 @@
---
title: Python 字符串格式化全指南
createTime: 2026/01/09 14:00:48
cover: /images/elysia/7.jpg
coverStyle:
layout: left
permalink: /archives/56ea3081-9c69-43d7-96c8-2812ec08be2c/
---
## 字符串格式化
我们经常会输出类似“亲爱的xxx你好你xx月的话费是xx余额是xx”之类的字符串而xxx的内容都是根据变量变化的所以需要一种简便的格式化字符串的方式。
在 Python 中可以使用很多种的字符串格式化方式,下面逐个列举。
### 字符串格式化的四种方式
#### 一、 %号
在Python中可以采用%来实现字符串格式化,%号格式化字符串的方式是从Python诞生之处就已经存在时至今日Python官方也未放弃使用%号,但是也不推荐使用这种格式化方式。
在字符串内部,`%s`表示用字符串替换,`%d`表示用整数替换,有几个占位符,后面就跟几个变量或值,顺序要对应。如果只有一个`%?`,括号可以省略。如果不太确定应该用什么,可以使用`%s`,它会把任何数据类型转换为字符串。
有的时候,字符串里的%是一个普通的字符,这个时候就需要转义,用`%%`来表示一个%。
下面是常见的字符串格式化替代符:
- `%c`格式化字符以及ASCII码
- `%s`:格式化字符串
- `%d`:格式化整数
- `%u`:格式化无符号整数
- `%o`:格式化无符号八进制数
- `%x`:格式化无符号十六进制数
- `%X`:格式化无符号十六进制数(大写)
- `%f`:格式化浮点数,可指定小数点后精度
- `%e`:用科学表示法格式化浮点数
- `%E`:同 %e
- `%g`%f 和 %e 的简写
- `%G`%f 和 %E 的简写
**Python 数字格式化示例:**
| 数字 | 格式 | 输出 | 描述 |
| :--- | :--- | :--- | :--- |
| 3.1415926 | `{:.2f}` | 3.14 | 保留小数点后两位 |
| 3.1415926 | `{:+.2f}` | +3.14 | 带符号保留小数点后两位 |
| -1 | `{:+.2f}` | -1.00 | 带符号保留小数点后两位 |
| 2.71828 | `{:.0f}` | 3 | 不带小数 |
| 5 | `{:0>2d}` | 05 | 数字补0填充左边宽度为2 |
| 5 | `{:x<4d}` | 5xxx | 数字补x填充右边宽度为4 |
| 10 | `{:x<4d}` | 10xx | 数字补x填充右边宽度为4 |
| 1000000 | `{:,}` | 1,000,000 | 以逗号分隔的数字格式 |
| 0.25 | `{:.2%}` | 25.00% | 百分比格式 |
| 1000000000 | `{:.2e}` | 1.00e+09 | 指数记法 |
| 13 | `{:>10d}` | 13 | 右对齐默认宽度为10 |
| 13 | `{:<10d}` | 13 | 右对齐宽度为10 |
| 13 | `{:^10d}` | 13 | 中间对齐宽度为10 |
| 11 | `'{:b}' '{:d}' '{:o}' '{:x}''{:#x}' '{:#X}'` | 1011 11 13 b0xb 0XB | 进制 |
**Python 字符串格式化的代码示例:**
```python
a=15 #定义变量a并赋值
b=12345678.1234567 #定义变量b并赋值
strs="I love Python!" #定义字符串strs并赋值
print("a=%05d"%a) #使用m控制输出位数空位补0
print("b=%8.3f"%b) #输出b用m.n控制输出的长度和小数点位数
print("%s"%strs) #正常输出字符串,用于做比较
print("%17s"%strs) #使用m控制输出字符串长度
print("%r"%strs) #使用%r输出字符串
print("%-17.5s"%strs) #使用-m.n进行左对齐、限制字符串长度和字符位数
print("a={0:05}".format(a)) #输出5位数字空位补0
print("b={0:,.3f}".format(b)) #输出b用千分位分隔并保留3位小数
print("{0:*^30}".format(strs)) #居中且使用*填充
```
**运行结果:**
```text
a=00015
b=12345678.123
I love Python!
I love Python!
'I love Python!'
I lov
a=00015
b=12,345,678.123
********I love Python!********
```
需要注意的一点是Python中的中文大小为两字符英文为一字符所以说在写的时候要格外留意。
#### 二、 str.format 格式化
该format方法是在Python2.6中引入的是字符串类型的内置方法。因为str.format的方式在性能(后面测试了一下,比%要慢)和使用的灵活性上都比%更胜一筹,所以推荐使用。
**1. 使用位置参数**
```python
# 按照位置一一对应
print('{} asked {} to do something'.format("egon","lili"))
print('{} asked {} to do something'.format("lili","egon"))
```
**2. 使用索引**
```python
# 使用索引取对应位置的值
print('{0}{0}{1}{0}'.format('x','y'))
```
**3. 使用关键字参数 or 字典**
```python
# 可以通过关键字or字典的方式格式化打破了位置带来的限制与困扰
print('我的名字是 {name}, 我的年龄是 {age}.'.format(age=18, name='egon'))
kwargs = {'name': 'egon', 'age': 18}
print('我的名字是 {name}, 我的年龄是 {age}.'.format(**kwargs)) # 使用**进行解包操作
```
关于解包详解可以参看:<https://blog.csdn.net/qq_36667170/article/details/121401668>
**4. 填充和格式化**
```python
# 先取到值,然后在冒号后设定填充格式:[填充字符][对齐方式][宽度]
# *<10左对齐总共10个字符不够的用*号填充
print('{0:*<10}'.format('开始执行')) # 开始执行******
# *>10右对齐总共10个字符不够的用*号填充
print('{0:*>10}'.format('开始执行')) # ******开始执行
# *^10居中显示总共10个字符不够的用*号填充
print('{0:*^10}'.format('开始执行')) # ***开始执行***
```
**5. 进度和进制**
```python
print('{salary:.3f}'.format(salary=1232132.12351)) #精确到小数点后3位四舍五入
print('{0:b}'.format(123)) # 转成二进制结果为1111011
print('{0:o}'.format(9)) # 转成八进制结果为11
print('{0:x}'.format(15)) # 转成十六进制结果为f
print('{0:,}'.format(99812939393931)) # 千分位格式化
```
#### 三、 f-Strings 格式化
虽然str.format()比%格式稍微高级了一些但是它还是有自己的缺陷。当需要传入的字符串过多时仍然会显得非常冗长。于是在Python3.6中引入了f-strings不仅比str.format更简洁性能上也更胜一筹。
f-string是以 f 或 F 开头的字符串,核心在于字符串中符号{}的使用。
**1. {} 中可以是变量名**
```python
name = 'egon'
age = 18
print(f'{name} {age}') # egon 18
print(F'{age} {name}') # 18 egon
```
**2. {} 中可以是表达式**
```python
# 可以在{}中放置任意合法的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
```
**3. 在类中的使用**
```python
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__
print(obj.__repr__()) # 触发__repr__
# 在f-Strings中的使用
print(f'{obj}') # 触发__str__
print(f'{obj!r}') # 触发__repr__
```
**4. 多行 f-Strings**
```python
# 当格式化字符串过长时如下列表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)
```
**5. 引号的嵌套**
```python
# 当字符串嵌套发送冲突时,与正常的字符串处理方式是一样的
# 1、外层为单引号内层嵌套也为单引号并且想要输入的内容也为单引号那么外层需要改用双引号
print("my name is 'egon'")
# 2、外层为单引号内层嵌套也为单引号并且想要输入的内容也为单引号需要用到转义
print('my name is \'egon\'')
```
**6. 括号的处理**
需要注意的是,反斜杠可以用来进行字符转义,但不能用在 {} 的表达式中,注释 # 号也不能出现在 {} 的表达式中。
```python
f'{1\2}' # 语法错误
f'{x#}' # 语法错误
```
所以当我们的输出的结果中需要包含{}时,类似于之前输出%的做法,需要在原有的基础上再套一层。
```python
print(f'{{天王盖地虎}}') # {天王盖地虎}
print(f'{{{{天王盖地虎}}}}') # {{天王盖地虎}}
```
#### 四、 三种字符串格式化方式的性能对比
```python
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.3338866999838501
print(res2) # 0.40734450006857514
print(res3) # 0.24273910000920296 最快
```
#### 五、 标准库模版
从Python2.4起Python标准库string引入了Template也可以用来格式化字符串所以说与前三种方式的一个显著的区别就是Template属于Python语言的核心语法特征使用方式如下。
```python
from string import Template
name='EGON'
t = Template('Hello $name!')
res=t.substitute(name=name)
print(res) # Hello EGON!
```
还有另外一个不同的地方是这个模板字符串不支持类似str.format那样的进制转换需要自己处理。
```python
from string import Template
name='EGON'
templ_string = 'Hello $name, there is a $error error!!!'
res=Template(templ_string).substitute(name=name, error=hex(12345))
print(res) # Hello EGON, there is a 0x3039 error!!!
```
另外稍微吐槽一下这种方式真的慢。使用模板字符串Template的最佳的时机就是当你的程序需要处理由用户提供的输入内容时。模板字符串是最保险的选择因为可以降低复杂性。其他一些复杂的字符串格式化技巧的可能会给你的程序带来安全漏洞。
### 总结
- 如果格式化的字符串是由用户输入的那么基于安全性考虑推荐使用Template。
- 如果使用的python3.6+版本的解释器推荐使用f-Strings。
- 如果要兼容python2.x版本的python解释器推荐使用str.format。
- 如果不是测试的代码,不推荐使用%。