我们对于可变数据(例如,列表,数据库等)的操作,一般包含增、删、改、查四个方面。
添加元素有一下几个方法:
append会把新元素添加到列表末尾
#定义变量A,默认有3个元素
A = ['xiaoWang','xiaoZhang','xiaoHua']
print("-----添加之前,列表A的数据-----A=%s" % A)
#提示、并添加元素
temp = input('请输入要添加的学生姓名:')
A.append(temp)
print("-----添加之后,列表A的数据-----A=%s" % A)
Copy
insert(index, object) 在指定位置index前插入元素object
strs = ['a','b','m','s']
strs.insert(3,'h')
print(strs) # ['a', 'b', 'm', 'h', 's']
Copy
通过extend将另一个可迭代对象中的元素逐一添加到列表末尾
必须是可迭代的元素
a = ['a','b','c']
b = ['d','e','f']
a.extend(b)
print(a) # ['a', 'b', 'c', 'd', 'e', 'f'] 将 b 添加到 a 里
print(b) # ['d','e','f'] b的内容不变
Copy
我们是通过指定下标来访问列表元素,因此修改元素的时候,为指定的列表下标赋值即可。
#定义变量A,默认有3个元素
A = ['xiaoWang','xiaoZhang','xiaoHua']
print("-----修改之前,列表A的数据-----A=%s" % A)
#修改元素
A[1] = 'xiaoLu'
print("-----修改之后,列表A的数据-----A=%s" % A)
Copy
所谓的查找,就是看看指定的元素是否存在,以及查看元素所在的位置,主要包含一下几个方法:
python中查找的常用方法为:
#待查找的列表
nameList = ['xiaoWang','xiaoZhang','xiaoHua']
#获取用户要查找的名字
findName = input('请输入要查找的姓名:')
#查找是否存在
if findName in nameList:
print('在列表中找到了相同的名字')
else:
print('没有找到')
Copy
结果1:(找到)
结果2:(没有找到)
说明:
in的方法只要会用了,那么not in也是同样的用法,只不过not in判断的是不存在
index用来查找元素所在的位置,如果未找到则会报错;count用来计算某个元素出现的次数。它们的使用和字符串里的使用效果一致。
>>> a = ['a', 'b', 'c', 'a', 'b']
>>> a.index('a', 1, 3) # 注意是左闭右开区间
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 'a' is not in list
>>> a.index('a', 1, 4)
3
>>> a.count('b')
2
>>> a.count('d')
0
Copy
类比现实生活中,如果某位同学调班了,那么就应该把这个条走后的学生的姓名删除掉;在开发中经常会用到删除这种功能。
列表元素的常用删除方法有:
movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情']
print('------删除之前------movieName=%s' % movieName)
del movieName[2]
print('------删除之后------movieName=%s' % movieName)
Copy
movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情']
print('------删除之前------movieName=%s' % movieName)
movieName.pop()
print('------删除之后------movieName=%s' % movieName)
Copy
movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情']
print('------删除之前------movieName=%s' % movieName)
movieName.remove('指环王')
print('------删除之后------movieName=%s' % movieName)
Copy
sort方法是将list按特定顺序重新排列,默认为由小到大,参数reverse=True可改为倒序,由大到小。
sort 对原列表永久改变
sorted对原列表不造成影响,只是临时改变
reverse方法是将list逆置。
>>> a = [1, 4, 2, 3]
>>> a
[1, 4, 2, 3]
>>> a.reverse() # 逆置,不排序
>>> a
[3, 2, 4, 1]
>>> a.sort() # 默认从小到大排序
>>> a
[1, 2, 3, 4]
>>> a.sort(reverse=True) # 从大到小排序
>>> a
[4, 3, 2, 1]
为了更有效率的输出列表的每个数据,可以使用循环来完成
namesList = ['xiaoWang','xiaoZhang','xiaoHua']
length = len(namesList) # 获取列表长度
i = 0
while i<length:
print(namesList[i])
i+=1
Copy
结果:
xiaoWang
xiaoZhang
xiaoHua
Copy
while 循环是一种基本的遍历列表数据的方式,但是最常用也是最简单的方式是使用 for 循环
namesList = ['xiaoWang','xiaoZhang','xiaoHua']
for name in namesList:
print(name)
Copy
结果:
xiaoWang
xiaoZhang
xiaoHua
Copy
# 使用中间变量
a = 4
b = 5
c = 0
c = a
a = b
b = c
print(a)
print(b)
直接:
a = 1
b = 2
a,b = b,a
手动实现冒泡排序(难)
nums = [5, 1, 7, 6, 8, 2, 4, 3]
for j in range(0, len(nums) - 1):
for i in range(0, len(nums) - 1 - j):
if nums[i] > nums[i + 1]:
a = nums[i]
nums[i] = nums[i+1]
nums[i+1] = a
print(nums)
print('办公室%d的人数为:%d'%(i,len(tempNames)))
i+=1
for name in tempNames:
print("%s"%name,end='')
print("\n")
print("-"*20)
Copy
类似while循环的嵌套,列表也是支持嵌套的
一个列表中的元素又是一个列表,那么这就是列表的嵌套
此处重点掌握怎么操作被嵌套的列表
>>> schoolNames = [
... [1, 2, 3],
... [11, 22, 33],
... [111, 222, 333]
... ]
>>> schoolNames[1][2] # 获取数字 33
33
>>> schoolNames[1][2] = 'abc' # 把 33 修改为 'abc'
>>> schoolNames
[[1, 2, 3], [11, 22, 'abc'], [111, 222, 333]]
>>> schoolNames[1][2][2] # 获取 'abc' 里的字符c
'c'
Copy
也就是说,操作嵌套列表,只要把要操作元素的下标当作变量名来使用即可。
一个学校,有3个办公室,现在有8位老师等待工位的分配,请编写程序,完成随机的分配
import random
# 定义一个列表用来保存3个办公室
offices = [[],[],[]]
# 定义一个列表用来存储8位老师的名字
names = ['A','B','C','D','E','F','G','H']
i = 0
for name in names:
index = random.randint(0,2)
offices[index].append(name)
i = 1
for tempNames in offices:
print('办公室%d的人数为:%d'%(i,len(tempNames)))
i+=1
for name in tempNames:
print("%s"%name,end='')
print("\n")
print("-"*20)
Python的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。
>>> aTuple = ('et',77,99.9)
>>> aTuple
('et',77,99.9)
Copy
说明: python中不允许修改元组的数据,包括不能删除其中的元素。但是,tuple可以重新赋值
index和count与字符串和列表中的用法相同
>>> a = ('a', 'b', 'c', 'a', 'b')
>>> a.index('a', 1, 3) # 注意是左闭右开区间
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: tuple.index(x): x not in tuple
>>> a.index('a', 1, 4)
3
>>> a.count('b')
2
>>> a.count('d')
0
Copy
定义只有一个元素的元组,需要在唯一的元素后写一个逗号
>>> a = (11)
>>> a
11
>>> type(a)
int
>>> a = (11,) # 只有一个元素的元组,必须要在元素后写一个逗号
>>> a
(11,)
>>> type(a)
tuple
Copy
# 第1种方式,使用中间变量
a = 4
b = 5
c = 0
c = a
a = b
b = c
print(a)
print(b)
# 第2种方式,直接交换。
a, b = 4, 5
a, b = b, a
print(a)
print(b)
当存储的数据要动态添加、删除的时候,我们一般使用列表,但是列表有时会遇到一些麻烦。
# 定义一个列表保存,姓名、性别、职业
nameList = ['xiaoZhang', '男', '木匠'];
# 当修改职业的时候,需要记忆元素的下标
nameList[2] = '铁匠'
# 如果列表的顺序发生了变化,添加年龄
nameList = ['xiaoWang', 18, '男', '铁匠']
# 此时就需要记忆新的下标,才能完成名字的修改
nameList[3] = 'xiaoxiaoWang'
Copy
有没有方法,既能存储多个数据,还能在访问元素的很方便就能够定位到需要的那个元素呢?
答:
字典
定义字典的格式:{键1:值1, 键2:值2, 键3:值3, …, 键n:值n}
变量info为字典类型:
info = {'name':'班长', 'id':100, 'sex':'f', 'address':'地球亚洲中国上海'}
info['name'] # 字典使用键来获取对应的值
Copy
说明:
在习惯上:
除了使用key查找数据,还可以使用get来获取数据
info = {'name':'班长','age':18}
print(info['age']) # 获取年龄
# print(info['sex']) # 获取不存在的key,会发生异常
print(info.get('sex')) # 获取不存在的key,获取到空的内容,不会出现异常
print(info.get('sex', '男')) # 获取不存在的key, 可以提供一个默认值。
Copy
注意,获取默认值不会修改字典内容。
字典的每个元素中的数据是可以修改的,只要通过key找到,即可修改
demo:
info = {'name':'班长', 'id':100}
print('修改之前的字典为 %s:' % info)
info['id'] = 200 # 为已存在的键赋值就是修改
print('修改之后的字典为 %s:' % info)
Copy
结果:
修改之前的字典为 {'name': '班长', 'id': 100}
修改之后的字典为 {'name': '班长', 'id': 200}
Copy
如果在使用 变量名[‘键’] = 数据 时,这个“键”在字典中,不存在,那么就会新增这个元素
demo:添加新的元素
info = {'name':'班长'}
print('添加之前的字典为:%s' % info)
info['id'] = 100 # 为不存在的键赋值就是添加元素
print('添加之后的字典为:%s' % info)
Copy
结果:
添加之前的字典为:{'name': '班长'}
添加之后的字典为:{'name': '班长', 'id': 100}
Copy
对字典进行删除操作,有一下几种:
demo:del删除指定的元素
info = {'name':'班长', 'id':100}
print('删除前,%s' % info)
del info['name'] # del 可以通过键删除字典里的指定元素
print('删除后,%s' % info)
Copy
结果
删除前,{'name': '班长', 'id': 100}
删除后,{'id': 100}
Copy
del删除整个字典
info = {'name':'monitor', 'id':100}
print('删除前,%s'%info)
del info # del 也可以直接删除变量
print('删除后,%s'%info)
Copy
结果
删除前,{'name': 'monitor', 'id': 100}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'info' is not defined
Copy
clear清空整个字典
info = {'name':'monitor', 'id':100}
print('清空前,%s'%info)
info.clear()
print('清空后,%s'%info)
Copy
结果
清空前,{'name': 'monitor', 'id': 100}
清空后,{}
集合(set)是一个无序的不重复元素序列,可以使用大括号 { } 或者 set() 函数创建集合。
注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
创建格式:
parame = {value01,value02,...}
或者
set((alue1,value2,...))
set([value1,value2,...])
set({value1,value2,...})
语法格式如下:
s.add(x)
>>>thisset = set(("Google", "Runoob", "Taobao"))
>>> thisset.add("Facebook")
>>> print(thisset)
{'Taobao', 'Facebook', 'Google', 'Runoob'}
Copy
s.update( x )
Copy
x 可以有多个,用逗号分开。
>>>thisset = set(("Google", "Runoob", "Taobao"))
>>> thisset.update({1,3})
>>> print(thisset)
{1, 3, 'Google', 'Taobao', 'Runoob'}
>>> thisset.update([1,4],[5,6])
>>> print(thisset)
{1, 3, 4, 5, 6, 'Google', 'Taobao', 'Runoob'}
Copy
语法格式如下:
s.remove( x )
将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误。
>>>thisset = set(("Google", "Runoob", "Taobao"))
>>> thisset.remove("Taobao")
>>> print(thisset)
{'Google', 'Runoob'}
>>> thisset.remove("Facebook") # 不存在会发生错误
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Facebook'
>>>
Copy
此外还有一个方法也是移除集合中的元素,且如果元素不存在,不会发生错误。格式如下所示:
s.discard( x )
Copy
>>>thisset = set(("Google", "Runoob", "Taobao"))
>>> thisset.discard("Facebook") # 不存在不会发生错误
>>> print(thisset)
{'Taobao', 'Google', 'Runoob'}
Copy
我们也可以设置随机删除集合中的一个元素,语法格式如下:
s.pop()
Copy
thisset = set(("Google", "Runoob", "Taobao", "Facebook"))
x = thisset.pop()
print(x)
print(thisset)
Copy
方法 | 描述 |
---|---|
add() | 为集合添加元素 |
clear() | 移除集合中的所有元素 |
copy() | 拷贝一个集合 |
difference() | 返回多个集合的差集 |
difference_update() | 移除集合中的元素,该元素在指定的集合也存在。 |
discard() | 删除集合中指定的元素, 不存在则不报错 |
intersection() | 返回集合的交集 |
intersection_update() | 删除集合中的元素,该元素在指定的集合中不存在。 |
isdisjoint() | 判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。 |
issubset() | 判断指定集合是否为该方法参数集合的子集。 |
issuperset() | 判断该方法的参数集合是否为指定集合的子集 |
pop() | 随机移除元素 |
remove() | 移除指定元素,不存在则报错 |
symmetric_difference() | 返回两个集合中不重复的元素集合。 |
symmetric_difference_update() | 移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。 |
union | 返回两个集合的并集 |
update() | 给集合添加元素 |
通过for … in … 我们可以遍历字符串、列表、元组、字典等
>>> a_str = "hello itcast"
>>> for char in a_str:
... print(char,end=' ')
...
h e l l o i t c a s t
Copy
>>> a_list = [1, 2, 3, 4, 5]
>>> for num in a_list:
... print(num,end=' ')
...
1 2 3 4 5
Copy
>>> a_turple = (1, 2, 3, 4, 5)
>>> for num in a_turple:
... print(num,end=" ")
1 2 3 4 5
Copy
>>> chars = ['a', 'b', 'c', 'd']
>>> i = 0
>>> for chr in chars:
... print("%d %s"%(i, chr))
... i += 1
...
0 a
1 b
2 c
3 d
Copy
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
>>> chars = ['a', 'b', 'c', 'd']
>>> for i, chr in enumerate(chars):
... print("%d %s"%(i, chr))
...
0 a
1 b
2 c
3 d
运算符 | Python 表达式 | 结果 | 描述 | 支持的数据类型 |
---|---|---|---|---|
+ | [1, 2] + [3, 4] | [1, 2, 3, 4] | 合并 | 字符串、列表、元组 |
* | [‘Hi!’] * 4 | [‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’] | 复制 | 字符串、列表、元组 |
in | 3 in (1, 2, 3) | True | 元素是否存在 | 字符串、列表、元组、字典 |
not in | 4 not in (1, 2, 3) | True | 元素是否不存在 | 字符串、列表、元组、字典 |
>>> "hello " + "world"
'hello world'
>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
>>> ('a', 'b') + ('c', 'd')
('a', 'b', 'c', 'd')
Copy
>>> 'ab' * 4
'ababab'
>>> [1, 2] * 4
[1, 2, 1, 2, 1, 2, 1, 2]
>>> ('a', 'b') * 4
('a', 'b', 'a', 'b', 'a', 'b', 'a', 'b')
Copy
>>> 'llo' in 'hello world'
True
>>> 3 in [1, 2]
False
>>> 4 in (1, 2, 3, 4)
True
>>> "name" in {"name":"chris", "age":18}
True
Copy
注意,in在对字典操作时,判断的是字典的键
Python包含了以下内置函数
序号 | 方法 | 描述 |
---|---|---|
1 | len(item) | 计算容器中元素个数 |
2 | del(item) | 删除变量 |
3 | max(item) | 返回容器中元素最大值 |
4 | min(item) | 返回容器中元素最小值 |
5 | range(start, end, step) | 返回容器中元素最小值 |
>>> len("hello itcast")
12
>>> len([1, 2, 3, 4])
4
>>> len((3,4))
2
>>> len({"a":1, "b":2})
2
Copy
注意:len在操作字典数据时,返回的是键值对个数。
del有两种用法,一种是del加空格,另一种是del()
>>> a = 1
>>> a
1
>>> del a
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> a = ['a', 'b']
>>> del a[0]
>>> a
['b']
>>> del(a)
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
Copy
>>> max("hello world")
'w'
>>> max([1,4,522,3,4])
522
>>> max({"a":1, "b":2})
'b'
>>> max({"a":10, "b":2})
'b'
>>> max({"c":10, "b":2})
'c'
Copy
>>> range(2, 10, 3)
[2, 5, 8]
>>> for x in range(2, 10, 3):
... print(x)
...
2
5
8
Copy
注意:range 可以生成数字供 for 循环遍历。三个数字分别为 起始、结束、步长
str.format()
方法通过字符串中的大括号{}
来识别替换字段 replacement field
,从而完成字符串的格式化。替换字段
由字段名 field name
和转换字段 conversion field
以及格式说明符 format specifier
组成,即一般形式为 {字段名!转换字段:格式说明符}。simple field name
和复合字段名 compound field name
。而转换字段和格式说明符都是可选的。form的完整格式是{字段名!转换字符:格式说明符}。其中字段名师必须的,而且可以分为简单字段名和复合字段名。
简单字段名由三中写法:
{}
{0}
大括号内省略字段名,传递位置参数。
{}
# 省略字段名传递位置参数
print('我叫{},今年{}岁。'.format('小明', 18))
"""
我叫小明,今年18岁。
"""
# 大括号个数可以少于位置参数的个数
print('我爱吃{}和{}。'.format('香蕉', '苹果', '大鸭梨'))
"""
我爱吃香蕉和苹果。
"""
# 大括号个数多于位置参数的个数则会报错
# print('我还吃{}和{}。'.format('西红柿'))
"""
IndexError: tuple index out of range
"""
Copy
可以通过数字形式的简单字段名传递位置参数。
# 通过数字形式的简单字段名传递位置参数
print('身高{0},家住{1}。'.format(1.8, '铜锣湾'))
"""
身高1.8,家住铜锣湾
"""
# 数字形式的简单字段名可以重复使用。
print('我爱{0}。\n她今年{1}。\n我也爱{0}。'.format('阿香', 17))
"""
我爱阿香。
她今年17。
我也爱阿香。
"""
# 体会把所有位置参数整体当成元组来取值
print('阿香爱吃{1}、{3}和{0}。'.format(
'榴莲', '臭豆腐', '皮蛋', '鲱鱼罐头', '螺狮粉'))
"""
阿香爱吃臭豆腐、鲱鱼罐头和榴莲。
"""
# 尝试一下越界错误
# print('{1}'.format('错误用法'))
"""
IndexError: tuple index out of range
"""
Copy
使用变量名形式的简单字段名传递关键字参数。
# 使用变量名形式的简单字段名传递关键字参数
print('我大哥是{name},今年{age}岁。'.format(name='阿飞', age=20))
"""
我大哥是阿飞,今年20岁。
"""
# 关键字参数的顺序可以随意调换
print('我大哥是{name},今年{age}岁。'.format(age=20, name='阿飞'))
"""
我大哥是阿飞,今年20岁。
"""
Copy
{}
不能和数字形式的字段名 {非负整数}
同时使用。# 混合使用数字形式和变量名形式的字段名
# 可以同时传递位置参数和关键字参数
print('这是一个关于{0}、{1}和{girl}的故事。'.format(
'小明', '阿飞', girl='阿香'))
"""
这是一个关于小明、阿飞和阿香的故事。
"""
# 但是关键字参数必须位于位置参数之后
# print('这是一个关于{0}、{1}和{girl}的故事。'.format(
# '小明', girl='阿香' , '阿飞'))
"""
SyntaxError: positional argument follows keyword argument
"""
# 数字也可以省略
print('这是一个关于{}、{}和{girl}的故事。'.format(
'小明', '阿飞', girl='阿香'))
# 但是省略字段名不能和数字形式的字段名同时出现
# print('这是一个关于{}、{1}和{girl}的故事。'.format(
# '小明', '阿飞', girl='阿香'))
"""
ValueError: cannot switch from automatic field numbering to manual field specification
"""
Copy
str.format()
方法还可以使用 *元组
和 **字典
的形式传参,两者可以混合使用。 位置参数、关键字参数、*元组
和 **字典
也可以同时使用,但是要注意,位置参数要在关键字参数前面,*元组
要在 **字典
前面。
# 使用元组传参
infos = '钢铁侠', 66, '小辣椒'
print('我是{},身价{}亿。'.format(*infos))
"""
我是钢铁侠,身家66亿。
"""
print('我是{2},身价{1}亿。'.format(*infos))
"""
我是小辣椒,身家66亿。
"""
# 使用字典传参
venom = {'name': '毒液', 'weakness': '火'}
print('我是{name},我怕{weakness}。'.format(**venom))
"""
我是毒液,我怕火。
"""
# 同时使用元组和字典传参
hulk = '绿巨人', '拳头'
captain = {'name': '美国队长', 'weapon': '盾'}
print('我是{}, 我怕{weapon}。'.format(*hulk, **captain))
print('我是{name}, 我怕{1}。'.format(*hulk, **captain))
"""
我是绿巨人, 我怕盾。
我是美国队长, 我怕拳头。
"""
# 同时使用位置参数、元组、关键字参数、字典传参
# 注意:
# 位置参数要在关键字参数前面
# *元组要在**字典前面
tup = '鹰眼',
dic = {'weapon': '箭'}
text = '我是{1},我怕{weakness}。我是{0},我用{weapon}。'
text = text.format(
*tup, '黑寡妇', weakness='男人', **dic)
print(text)
"""
我是黑寡妇,我怕男人。我是鹰眼,我用箭。
"""
Copy
.
点号[]
中括号.
点号传递位置参数
{数字.属性名}
class Person(object):
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
p = Person('zhangsan',18,'female')
print('姓名是{0.name},年龄是{0.age},性别是{0.gender}'.format(p))
print('姓名是{.name}'.format(p)) # 只有一个替换字段时,可以省略数字
Copy
[]
中括号# 中括号用法:用列表传递位置参数
infos = ['阿星', 9527]
food = ['霸王花', '爆米花']
print('我叫{0[0]},警号{0[1]},爱吃{1[0]}。'.format(
infos, food))
"""
我叫阿星,警号9527,爱吃霸王花。
"""
# 中括号用法:用元组传递位置参数
food = ('僵尸', '脑子')
print('我叫{0[0]},年龄{1},爱吃{0[1]}。'.format(
food, 66))
"""
我叫僵尸,年龄66,爱吃脑子。
"""
# 中括号用法:用字典传递位置参数
dic = dict(name='阿星', pid=9527)
print('我是{[name]}!'.format(
dic))
# 多个替换字段,不能省略数字
print('我是{0[name]},警号{0[pid]}。'.format(
dic))
"""
我是阿星!
我是阿星,警号9527。
"""
Copy
转换字段 conversion field
的取值有三种,前面要加 !
:
s
:传递参数之前先对参数调用 str()
r
:传递参数之前先对参数调用 repr()
a
:传递参数之前先对参数调用 ascii()
ascii()
函数类似repr()
函数,返回一个可以表示对象的字符串。 但是对于非ASCII
字符,使用\x
,\u
或者\U
转义。
# 转换字段
print('I am {!s}!'.format('Bruce Lee 李小龙'))
print('I am {!r}!'.format('Bruce Lee 李小龙'))
print('I am {!a}!'.format('Bruce Lee 李小龙'))
"""
I am Bruce Lee 李小龙!
I am 'Bruce Lee 李小龙'!
I am 'Bruce Lee \u674e\u5c0f\u9f99'!
"""
Copy
格式说明符使用过于复杂,且实际使用场景不多,暂不讨论。