一文了解python 3 字符串格式化 F-string 用法
从python3.6开始,引入了新的字符串格式化方式,f-字符串.这使得格式化字符串变得可读性更高,更简洁,更不容易出现错误而且速度也更快.
在Python3.6之前,有两种将Python表达式嵌入到字符串文本中进行格式化的主要方法:%-formatting和str.format()。
在本文后面,会详细介绍f-字符串的用法.在此之前,让我们先来复习一下python中字符串格式化的方法.
python中传统的字符串格式化方法.
在python3.6之前,我们有两种方式可以用来格式化字符串.
- 占位符+%的方式
- str.format()方法
首先复习一下这两种方式的使用方法以及其短板.
占位符+%的方式
这种方式算是第0代字符串格式化的方法,很多语言都支持类似的字符串格式化方法.在python的文档中,我们也经常看到这种方式.
但是!!!BUT!!!
占位符+%的方式并不是python推荐的方式.
NoteTheformattingoperationsdescribedhereexhibitavarietyofquirksthatleadtoanumberofcommonerrors(suchasfailingtodisplaytuplesanddictionariescorrectly).Usingthenewerformattedstringliterals,thestr.format()interface,ortemplatestringsmayhelpavoidtheseerrors.Eachofthesealternativesprovidestheirowntrade-offsandbenefitsofsimplicity,flexibility,and/orextensibility.(Python3doc)
文档中也说了,这种方式对于元组等的显示支持的不够好.而且很容易产生错误.
而且不符合python代码简洁优雅的人设...
「如何使用占位符+%的方式」
如果你接触过其他的语言,这种方式使用起来会有一种诡异的亲切感,这种亲切感会让你抓狂,内心会暗暗的骂上一句,艹,又是这德行...(这句不是翻译,是我的个人感觉,从来都记不住那么多数据类型的关键字...)
In[1]:name='Eric' In[2]:'Hello,%s'%name Out[2]:'Hello,Eric'
如果要插入多个变量的话,就必须使用元组.像这样
In[3]:name='Eric' In[4]:age=18 In[5]:'Hello%s,youare%d.'%(name,age) Out[5]:'HelloEric,youare18.'
「为什么说占位符+%的方式不是最好的办法(个人认为是这种方式是一种最操蛋的操作)」
上面有少量的变量需要插入到字符串的时候,这种办法还行.但是一旦有很多变量需要插入到一个长字符串中...比如...
In[6]:first_name="Eric" ...:last_name="Idle" ...:age=74 ...:profession="comedian" ...:affiliation="MontyPython" In[7]:"Hello,%s%s.Youare%s.Youarea%s.Youwereamemberof%s."%(first_name,last_name,age,profession,affiliation) Out[7]:'Hello,EricIdle.Youare74.Youareacomedian.YouwereamemberofMontyPython.'
像上面这个例子,代码可读性就很差了.(对读和写的人都是一种折磨...)
使用str.format()的方式
在python2.6之后,引入了str.format()函数,可以用来进行字符串的格式化.它通过调用对象的__format__()方法(PEP3101中定义)来将对象转化成字符串.
在str.format()方法中,通过花括号占位的方式来实现变量插入.
In[8]:'hello,{}.Youare{}.'.format(name,age) Out[8]:'hello,Eric.Youare74.'
甚至可以给占位符加索引.
In[9]:'hello,{1}.Youare{0}.'.format(age,name) Out[9]:'hello,Eric.Youare74.'
如果要在占位符中使用变量名的话,可以像下面这样
In[10]:person={'name':'Eric','age':74} In[11]:'hello,{name}.youare{age}'.format(name=person['name'],age=person['age']) Out[11]:'hello,Eric.youare74'
当然对于字典来说的话,我们可以使用**的小技巧.
In[15]:'hello,{name}.youare{age}'.format(**person) Out[15]:'hello,Eric.youare74'
str.format()方法对于%的方式来说已经是一种很大的提升了.但是这并不是最好的方式.
「为什么format()方法不是最好的方式」相比使用占位符+%的方式,format()方法的可读性已经很高了.但是同样的,如果处理含有很多变量的字符串的时候,代码会变得很冗长.
>>>first_name="Eric" >>>last_name="Idle" >>>age=74 >>>profession="comedian" >>>affiliation="MontyPython" >>>print(("Hello,{first_name}{last_name}.Youare{age}."+ >>>"Youarea{profession}.Youwereamemberof{affiliation}.")\ >>>.format(first_name=first_name,last_name=last_name,age=age,\ >>>profession=profession,affiliation=affiliation)) 'Hello,EricIdle.Youare74.Youareacomedian.YouwereamemberofMontyPython.'
当然,我们也可以通过字典的方式直接传入一个字典来解决代码过长的问题.但是,python3.6给我们提供了更便利的方式.
f-字符串,一种新的增强型字符串格式化方式
这种新的方式在PEP498中定义.(原文写到这里的时候,作者可能疯了,balabla说了一长串,冷静的我并没有翻译这些废话...)这种方式也被叫做formattedstringliterals.格式化的字符串常亮...ummm...应该是这么翻译吧...
这种方式在字符串开头的时候,以f标识,然后通过占位符{}+变量名的方式来自动解析对象的__format__方法.如果想了解的更加详细,可以参考python文档
一些简单的例子
「使用变量名作为占位符」
In[16]:name='Eric' In[17]:age=74 In[18]:f'hello{name},youare{age}' Out[18]:'helloEric,youare74'
「这里甚至可以使用大写的F」
In[19]:F'hello{name},youare{age}' Out[19]:'helloEric,youare74'
你以为这就完了吗?
不!
事情远不止想象的那么简单...
在花括号里甚至可以执行算数表达式
In[20]:f'{2*37}' Out[20]:'74'
如果数学表达式都可以的话,那么在里面执行一个函数应该不算太过分吧...
In[22]:defto_lowercase(input): ...:returninput.lower() ...: In[23]:name='ERICIDLE' In[24]:f'{to_lowercase(name)}isfunny' Out[24]:'ericidleisfunny'
你以为这就完了吗?
不!
事情远不止想象的那么简单...
这玩意儿甚至可以用于重写__str__()和__repr__()方法.
classComedian: def__init__(self,first_name,last_name,age): self.first_name=first_name self.last_name=last_name self.age=age def__str__(self): returnf"{self.first_name}{self.last_name}is{self.age}." def__repr__(self): returnf"{self.first_name}{self.last_name}is{self.age}.Surprise!" >>>new_comedian=Comedian("Eric","Idle","74") >>>f"{new_comedian}"'EricIdleis74.'
关于__str__()方法和__repr__()方法.这是对象的两个内置方法.__str()__方法用于返回一个便于人类阅读的字符串.而__repr__()方法返回的是一个对象的准确释义.这里暂时不做过多介绍.如有必要,请关注公众号吾码2016(公众号:wmcoding)并发送str_And_repr
默认情况下,f-关键字会调用对象的__str__()方法.如果我们想调用对象的__repr__()方法的话,可以使用!r
>>>f"{new_comedian}" 'EricIdleis74.' >>>f"{new_comedian!r}" 'EricIdleis74.Surprise!'
更多详细内容可以参考这里
多个f-字符串占位符
同样的,我们可以使用多个f-字符串占位符.
>>>name="Eric" >>>profession="comedian" >>>affiliation="MontyPython" >>>message=( ...f"Hi{name}." ...f"Youarea{profession}." ...f"Youwerein{affiliation}." ...) >>>message 'HiEric.Youareacomedian.YouwereinMontyPython.'
但是别忘了,在每一个字符串前面都要写上f
同样的,在字符串换行的时候,每一行也要写上f.
>>>message=f"Hi{name}."\ ...f"Youarea{profession}."\ ...f"Youwerein{affiliation}."... >>>message 'HiEric.Youareacomedian.YouwereinMontyPython.'
但是如果我们使用"""的时候,不需要每一行都写.
>>>message=f""" ...Hi{name}. ...Youarea{profession}. ...Youwerein{affiliation}. ...""" ... >>>message '\nHiEric.\nYouareacomedian.\nYouwereinMontyPython.\n'
关于f-字符串的速度
f-字符串的f可能代表的含义是fast,因为f-字符串的速度比占位符+%的方式和format()函数的方式都要快.因为它是在运行时计算的表达式而不是常量值.(那为啥就快了呢...不太懂啊...)
❝“F-stringsprovideawaytoembedexpressionsinsidestringliterals,usingaminimalsyntax.Itshouldbenotedthatanf-stringisreallyanexpressionevaluatedatruntime,notaconstantvalue.InPythonsourcecode,anf-stringisaliteralstring,prefixedwithf,whichcontainsexpressionsinsidebraces.Theexpressionsarereplacedwiththeirvalues.”(PEP498)
❞
(官方文档,咱不敢翻,大意就是f-字符串是一个在运行时参与计算的表达式,而不是像常规字符串那样是一个常量值)
在运行时,花括号内的表达式在其自己的作用域内求职,单号和字符串的部分拼接到一起,然后返回.
下面我们来看一个速度的对比.
importtimeit time1=timeit.timeit("""name='Eric'\nage=74\n'%sis%s'%(name,age)""",number=100000) time2=timeit.timeit("""name='Eric'\nage=74\n'{}is{}'.format(name,age)""",number=100000) time3=timeit.timeit("""name='Eric'\nage=74\nf'{name}is{age}'""",number=100000)
从结果上看的话,f-字符串的方式速度要比其他两种快.
0.030868000000000007 0.03721939999999996 0.0173276
f-字符串的一些细节问题
「引号的问题」在f-字符串中,注意成对的引号使用.
f"{'EricIdle'}" f'{"EricIdle"}' f"""EricIdle""" f'''EricIdle'''
以上这几种引号方式都是支持的.如果说我们在双引号中需要再次使用双引号的时候,就需要进行转义了.f"The\"comedian\"is{name},aged{age}."
「字典的注意事项」
在字典使用的时候,还是要注意逗号的问题.
>>>comedian={'name':'EricIdle','age':74} >>>f"Thecomedianis{comedian['name']},aged{comedian['age']}." >>>f'Thecomedianis{comedian['name']},aged{comedian['age']}.'
比如上面两条语句,第三句就是有问题的,主要还是引号引起的歧义.
「花括号」如果字符串中想使用花括号的话,就要写两个花括号来进行转义.同理,如果想输出两个花括号的话,就要写四个...
>>>f"{{74}}"'{74}' >>>f"{{{{74}}}}"
「反斜杠」反斜杠可以用于转义.但是!!!BUT!!!在f-字符串中,不允许使用反斜杠.
>>>f"{\"EricIdle\"}" File"",line1 f"{\"EricIdle\"}" ^SyntaxError:f-stringexpressionpartcannotincludeabackslash
像上面这个的解决办法就是
>>>name="EricIdle" >>>f"{name}"'EricIdle'
「行内注释」f-字符串表达式中不允许使用#符号.
总结和参考资料
我们依旧可以使用老的方式进行字符串格式化输出.但是通过f-字符串,我们现在有了一种更便捷,更快,可读性更高的方式.根据python教义,ZenofPython:
「thereshouldbeone–andpreferablyonlyone–obviouswaytodoit.」(编程还编出哲理来了...实在不会翻,有一种醍醐灌顶的感觉,内心浮现一个声音,卧槽!好有道理,仿佛自己升华了,但是仔细想想...这句话到底啥意思呢...)
更多的参考资料(我也只是写在这里,反正我是没有闲心看它的...):
PEP502:StringInterpolation-ExtendedDiscussion
PEP536:FinalGrammarforLiteralStringInterpolation
到此这篇关于一文了解python3字符串格式化F-string用法的文章就介绍到这了,更多相关python字符串格式化f-string内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。