目录
一、格式占位符及函数str()、repr()、ascii()
1、格式占位符(格式转换符)
2、函数str()、repr()、ascii()
二、 f''、str.format()和str%()格式化表达式中对对象的引用
三、 f''、str.format()和str%()格式化表达式增加描述的字符
有时候我们需要在print()输出时对对象进行处理或描述,使得输出符合我们的要求,或更好地呈现结果以便我们理解(也即对输出结果增加可读性),这时候,我们可以对print的打印对象进行一些相关设置,使得print的打印输出是以一定的格式输出,以实现我们打印输出的要求,通常我们用f''、str.format()和str%()的字符串格式化(格式化字符串、格式化输出)来实现print的打印效果。当然,f''、str.format()和str%()也可以用在其它场景。f''字符串格式化通常称为f-string字符串格式化。
对于f''、str.format()和str%()的字符串格式化的具体使用,有的会涉及到占位符,因而,这里先介绍python的格式占位符(format placeholder)。这三种字符串格式化也可以简写为f格式化、format格式化、%操作符格式化。
格式占位符,该名称起源于C语言,表示在该位置有输入或输出(比如:scanf()、printf()等函数中使用),占位符表示在该位置产生某种格式的数据,在python中,也可以理解为格式转换符,也有表示为对象做相关的转换的意思,这里沿用以前的称呼。下面表1-1中是几种常用的格式占位符(格式转换符)。
表1-1 常用格式占位符(格式转换符)
s |
字符串 (采用str()的显示),也可用ns,n表示输出宽度,即输出的占位个数 |
r |
字符串 (采用repr()的显示),也可用nr,n同上 |
a |
字符串 (采用ascii()的显示),也可用na,n同上 |
c |
单个字符,也可用nc,n同上 |
b |
二进制整数,只能在f''、str.format()中使用,也可用nb,n同上 |
d |
十进制整数,也可用nd,n同上 |
o |
八进制整数,也可用no,n同上 |
x |
十六进制整数,可以用X,也可用nx,n同上 |
f |
十进制的浮点数,也即小数 |
.mf |
m是精度,表示保留m位小数 |
n.mf |
n表示输出宽度,即输出的占位个数,m表示保留m位小数,.m可以缺省 |
e |
科学计数法,指数形式,底数为e(相当于10),也可用E |
.me |
m表示保留m位小数 |
n.me |
n表示输出宽度,即输出的占位个数,m表示保留m位小数,.m可以缺省 |
g |
若指数小于-4或指数大于5,则使用e,否则,默认用d或f,也可用G |
.mg |
保留m位(个)有效数字,若指数小于-4或大于m-1,则使用e,否则,使用d |
n.mg |
n为输出宽度,即输出的占位个数,m同上 ,值的形式同上,.m可以缺省 |
% |
%字符 |
上面列出的格式占位符在str%()、f''、str.format()中都会增加相应的符号,比如:str%()中的占位符会增加符号%,在f''和str.format()格式化表达式中是用其它符号。str%()不支持转换为二进制%b,会提示unsupported format character 'b'。
表1-1中格式占位符s采用的是函数str()的结果,获取适合人阅读的文本字符串。格式占位符r采用的是函数repr()的结果,将对象转化为比较适合解释器读取的形式,其返回值也是字符串类型,从使用角度上讲,repr()函数给表达式增加一对引号的作用。
str(),repr()分别调用了__str__()、__repr__()方法,object类含有这两个方法,而python所有类都继承了object类,因而python的类都继承了__str__()、__repr__()方法。函数print在打印时会默认调用__str__()方法,因此,函数print的打印输出实际都是自动转换为了字符串格式。
sr1 = 'Hello,Python\n'
#print打印默认调用了__str__()方法,显示出的文本字符串,适合人阅读,
#相当于执行了转义符\n。
print(sr1)
#repr(sr1)实际获得的值为"'Hello,Python\n'",
#但经过print打印调用了__str__()方法,显示为'Hello,Python\n'。
print(repr(sr1))
#上面相当于下面。
#格式占位符表示该位置会产生一个什么格式的数据。
#str%()中格式占位符都会增加符号%,下面%r表示该位置产生repr()函数返回的字符串格式的数据,
#实际也是依次引用右边小括号的实参进行格式化。
#下面print打印也调用了__str__()方法。
print('%r'%(sr1))
#数字的字符串格式。
sr2=str(123)
print(type(sr2),sr2)
#对于字符串,增加引号。
print(type(repr(sr2)),repr(sr2))
#对于非字符串的整型,增加引号。
print(type(repr(123)),repr(123))
print('%s'%(123))#s即为str()
print('%r'%(123))#r即为repr()
运行结果:
函数repr()的作用相当于增加一对引号,可以用eval()函数把repr()的结果恢复到原数据。解析函数eval的用法可参考本博客第九章的内容。
sr1 = 'Hello,Python'
#根据eval的执行特点,下面是可行的,但不能直接用eval(sr1)。
#eval执行了"'Hello,Python'",得到结果'Hello,Python',sr1引用了它。
sr1=eval(repr(sr1))
#print打印默认调用了__str__()方法,显示出的文本字符串,适合人阅读。
print(sr1)
运行结果:
我们可以在类中重写__str__()或__repr__()方法,类在实例化时会自动执行重写的__str__()或__repr__()方法,这个自动执行类似__init__(),当两者都重写时,默认执行__str__()。
class Group:
def __init__(self,name,age):
self.name = name
self.age = age
#返回类对象地址,打印出类对象地址。
print(Group('Bor',23))
class Member:
def __init__(self,name,age):
self.name = name
self.age = age
def __repr__(self):
return ('名字是:%s,年龄是:%d')%(self.name,self.age)
#重写了__repr__方法,类实例化时自动执行__repr__方法。
#打印自动执行__repr__方法的返回值。
print(Member('Bor',23))
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
def __repr__(self):
return ('名字是:%s,年龄是:%d')%(self.name,self.age)
def __str__(self):
return ('name is %s,age is %d')%(self.name,self.age)
#重写了__repr__、__str__方法,类实例化时默认自动执行__str__方法。
#打印自动执行__str__方法的返回值。
print(Student('Bor',23))
运行结果:
表1-1中格式占位符a采用的是函数ascii()的结果,返回是根据ASCII编码标准解码的字符,若不能用ASCII编码,则会用 \x、\u (或 \U) 进行转义,然后增加引号,类似repr()函数,只是解码时的编码标准不同。
sr1='abc\n'
#对字符串增加引号,是ASCII解码的字符串。
print(type(ascii(sr1)),ascii(sr1))
print('%a'%(sr1))
sr2='你好'
#对汉字字符串增加引号,不能用ASCII解码,则会用\x、\u进行转义。
print(type(ascii(sr2)),ascii(sr2))
print('%a'%(sr2))
n1=129
#对整型增加引号,是ASCII解码的数字字符串。
print(type(ascii(n1)),ascii(n1))
print('%a'%(n1))
print('\n')
print(type(repr(sr2)),repr(sr2))
print(type(sr2),sr2)
print(type(repr(n1)),repr(n1))
print(type(str(n1)),str(n1))
print('%s'%(n1))
运行结果:
ascii()的结果用ASCII 编码标准解码或进行转义,然后增加引号。Type和ASCII编码标准可以参加后面相关内容。
下面,我们将讲述f''、str.format()和str%()的字符串格式化的具体使用。f''字符串格式化通常称为f-string字符串格式化。
f''、str.format()、str%()对对象的引用的基本形式为:
f’{name}’, 该表达式不支持对参数对象的引用,其中name表示名称(对象的标识),是对对象的引用,这里的name是不能缺省的;
‘{name}’. format(),其中,format()的小括号里是参数,可以是位置参数或关键字参数,即支持str.format(*args,**kwargs),name也是对这里的实参的对象的引用,但这里的name是format()中的位置实参对应的序数(序数从0开始)或关键字参数的关键字,当format()中为关键字实参,name不能缺省,若引号里是对仅有的一个位置实参整体操作或按顺序对每个位置实参整体操作,则表示序数的name可以缺省,若是对位置实参进行局部操作,则表示序数的name不可以缺省;
‘%(name)’% (),该表达式不适合引用关键字参数,其中, 右边小括号()里是参数,若参数为字典,可以使用name对字典中的对象进行引用,否则,name缺省。另外,右边小括号()中若只有一个参数,这个小括号可以缺省。
f''的name引用与参数无关,而str.format()、str%()的name引用与参数有关,而且str.format()、str%()对字典中的对象进行引用比较特殊,与关键字参数的引用相比有差异,str.format()、str%()对字典中的对象进行引用,只能是某些数据类型才能作为引用name,而且这个name是以标识符的形式(样式)进行引用,但name并不一定符合标识符的构成标准(规范),具体参加下面实例,下面实例是各格式表达式对对象的引用。
sr1,sr2='ab','cd'
te1 = {'kr': 'ij', 10: 31, '12': 89,'15y':76}
lt1=[1,2,3]
print("f'':")
#f''是通过名称引用对象,对字典的键值的引用是通过键名引用,这也是字典的引用方式。
print(f'{sr1},{sr2},{te1},{te1["kr"]},{te1[10]},{te1["12"]},{te1["15y"]}')
print('\nstr.format():')
#对于位置实参,str.format()若是按顺序引用小括号()中的位置实参,{}中可缺省序数。
#不能出现有的有序数,有的缺省序数这种形式。对于关键字实参,关键字不能缺省。
print('{},{z},{},{}'.format(sr1,sr2,te1,z=3))
#但引用对象的局部的元素时,应该使用序数。
print('{0},{1[0]},{2}'.format(sr1,sr2,te1))
#序数代表了对应的位置实参。
print('{1},{2},{0}'.format(sr1,sr2,te1))
#下面是借助键名对位置参数字典中的对象(键值)进行引用,
#但不支持键名为数字字符串的,其它都支持,并且引用方式类似标识符引用,
#而不是直接使用键名(字典的引用方式)。
#下面键名10、'15y'类似标识符进行引用,但不支持数字字符串键名'12',
#注意,对参数te1里面再次进行引用,这时不再是参数引用。
print('{0[kr]},{0[10]},{0[15y]}'.format(te1))
#下面是关键字参数进行引用,因为函数的关键字参数对应为变量,关键字参数实际也是变量,
#而变量名(变量名也是标识符)的首个符号不能是数字,因此,下面只能使用关键字kr。
#下面是对实参**te1进行解包,对关键字参数进行引用,具体可以参加前面讲到的动态参数。
print('{kr}'.format(**te1))
#下面是对位置实参的引用。
print('{2},{0},{1}'.format(*lt1))
#str.format()可以通过关键字引用关键字实参,也可以引用其局部元素。
print('{y},{y[1]}'.format(y=[7,8,9]))
print('\nstr%():')
#str%()不适合引用关键字参数。
#格式占位符表示该位置会产生一个什么格式的数据。
#str%()中格式占位符都会增加符号%,下面%s表示该位置产生字符串格式的数据,
#实际也是依次引用右边小括号的实参进行格式化。
print('%s,%s'%(sr1,sr2))
#借助键名对位置参数字典中的对象进行引用,
#但不支持数字的键名,其它都支持,并且引用方式类似标识符引用,
#而不是直接使用键名(字典的引用方式)。
#下面键名'kr'、'12'、'15y'类似标识符进行引用,但不支持数字键名10。
print('%(kr)s,%(12)s,%(15y)s'%(te1))
print('\n通过路径引用对象:')
class AA:
a1=1
a2=2
print(f'{AA.a1},{AA.a2}')
print(f'{AA().a1},{AA().a2}')
#下面只能变成关键字参数才能引用。
print('{t.a1},{t.a2}'.format(t=AA))
print('{t.a1},{t.a2}'.format(t=AA()))
运行结果:
f''、str.format()、str%()的使用有一定互补性,各有自己的特点。而且,f''、str.format()可以不使用占位符,上面代码中f''、str.format()未使用占位符,但str%()需要占位符。f''的name必须存在,不能缺省。
在python中,对对象的引用一般有三种基本形式。一种是借助序号来引用,比如: sr1[2],2是索引。另一种是借助键名来引用,是键名性质的引用,比如:字典dt1[‘bd’],‘bd’是键名。还有一种是借助标识符来引用,比如:变量num=856,num是变量。从上面例子,我们可以看到str.format()、str%()的name引用存在一定的特殊性,存在一种近似标识符的引用,但又不符合标识符的规范。
sr1='abc'
k1=len(sr1)
#f''
print(f'字符串{sr1}的长度是{k1}')
#或用str.format()
print('字符串{0}的长度是{1}'.format(sr1,k1))
#或用str%()
print('字符串%s的长度是%d'%(sr1,k1))
运行结果:
上面列出了f''、str.format()和str%()三种格式化表达式。上面打印输出就是以一定格式进行打印输出,这种格式化输出,其打印的结果更有可读性,若用print(sr1,k1),显然可读性比较差,单纯看结果不直观,但上面描述性的格式化打印,打印输出的结果让我们一目了然。
Python中f‘‘、str.format()和str%()的字符串格式化详解(2):
https://blog.csdn.net/thefg/article/details/130941724