在开始今天的正文之前
,
先
让
我
们
看一下
f
字符串是怎么回事
?
对于一个声称关注于以一个正确的方式去处理大部分情形的语言而言,
python
里面的字符串格式化正在受着猛烈的冲击,而且每一年都变得更加多种多样。以
python 3.6
开始,我们有
3
种方式格式化字符串,(简单的外部连接或者使用
string.Template
):
使用
%
操作符
str.format
内插替换字符串
%-
格式化
%-
格式化至少从版本
1.0
开始就是
python
的一部分了,如果你做了用
python 3
以前的
python
版本做了一些事后,你就应该知道这些。
"%s%s" % ('Hello', 'Python',)
这只支持有限的类型集,所以在将其传递给字符串格式器之前你必须在将你的自定义对象转化至这些类型集中的一种。
许多年以后,原始的字符串数据类型以一种格式方式而延伸了:
str.format()
这同一些像上下文管理器的东西一并载入了
2008
年
8
月发布的
python2.6
中。就像在
PEP-3101
中详细讲的一样,它尝试着去处理一些老式
%
二进制操作符中的短板,比如
%
只支持有限的类型集或者实际上处理整个表达式的右侧组成部分,而这会在一些特殊的条件下会导致错误。
>>>"%s" % ("lala",)
'lala'
>>>"%s" % "lala"
'lala'
因为
.format
是一种方法而不是一种操作符(对应到一种二进制方法),处理的参数更加明确。如果你遇到一个字符串,让它就会被解释成为字符串。如果你遇到一个只包含一个字符串的元组,它就会被解释成一个包含一个字符串的元组:
>>>"{}".format("lala")
'lala'
>>>"{}".format(("lala",))
"('lala',)"
相比于
%
,它也支持提供给你参数名而不需要使用字典:
"{firstname}{lastname}".format(firstname="Horst",lastname="Gutmann")
开始,这原本打算是作为
%
操作符的完全代替(计划打击
python 3.1
中的老式格式化函数),但是这永远都不可能发生了,因为这个字符串格式器的核心特点都与老式的
%
操作符大部分都是相似的,但就语法稍微有点不一样以及就我看而言更加直观而已。事实上,正是因为如此,
Ulrich
于是就和我创造了
pyformat.info
来帮助人们过渡到新的系统。
但是很显然的是,
PEP-3101
并不会在只消除老式的特点集上就停止脚步,它依旧引入了一个协议来允许与自定义类之间更加通用的交互。
classCountry:
def __init__(self, name, iso):
self.name, self.iso = name, iso
def __format__(self, spec):
if spec == 'short':
return self.iso
return self.name
country =Country("Austria", "AUT")
print("{}".format(country))
print("{:short}".format(country))
你能将
format
方法想象成为一个
str
来进行字符串格式化,这样你就能通过各种选项。一旦在你的对象中有
format
方法,它就会被用来替代
str
当你使用
format-method
时(除非你做了一些像
"{!s}".format(country)"
事情的时候)
实际上你能在
python 3.4
的
datatime.date
类中找到一个很好地例子去解释怎么使用它。
classdate:
...
def __format__(self, fmt):
if len(fmt) != 0:
return self.strftime(fmt)
return str(self)
这让你在
“parent”
字符串格式中直接格式化日期,而你不再首先将日期转化成字符串然后再将其传递到字符串格式器中:
importdatetime
print("Todayis {:%A}".format(datetime.datetime.now()))
# Today isThursday
PEP-0498:
字符串内插
尽管这就是现在进行字符串格式化的推荐方式,但是
.format
太繁琐了:
a ="Hello"
b ="World"
"{}{}".format(a, b)
# vs.
"%s%s" % (a, b,)
pep-0498
通过提供在其他语言如
Ruby
,
Scala
以及
Perl
中已经普及相当长一段时间的东西:内插字符串,尝试着去改善这种处境。其中表达式能够直接被整合进字符串,而这就意味着你不用明确地调用任何额外的函数。
ES2015
把这个特性引入到
JavaScript-world
中的
“recently”
中,这被称为
“
模板字符串
”
:
constusername = "Horst";
constwelcomeMsg = `Hello, ${username}!`;
在
python
中反引号在
python3.0
以上版本中已成为历史了,因此它们并不可得。再次引入它们可能会再一次影响
python
的基本语法。作为代替,另外的文字前缀被引入了:
f
。
a ="Hello"
b ="World"
f"{a}{b}"
f"{a+ ' ' + b}"
你不再需要直接调用一个字符串的
.format()
方法,但是要简单地用前缀
f
来标记格式以及内联最终字符串中你想要包括的表达式,不然它们就会被期望着去提供如同你从
.format()
函数得到的相同功能。这些格式化字符串也在文档中被称为
“f
字符串
”
。
那事实上看起来十分美好,但因为
python 3.6
会在未来的
12
个月后才能够发布,你恐怕还要等上一段时间。话虽这么说,代码却已经在那儿了,所以你能做的就是获取一个
python 3.6
预发布版本或者使用一些像
pyenv
的小诀窍,然后让它运行就行了。
其实还有很多,这里有其他的
PEP
(
0501
),它想要引入
i-strings
而这类字符串导致了字符串的懒惰计算,以至于例如你能在最终评估之前能做一些国际化(
i18n
)或者安检。虽然这个提案已延缓至进一步的讨论,但这看起来是个很好的想法。
但是回到
f-strings
:如果你想要去了解更多关于为什么字符串内插解决了它存在的方式,那就请看一看
PEP-0502
,这里面包括了从其他语言上获得这个特性的灵感以及背后的动机的详细讨论。
接下来
继续
f
字符串的一些小
问题
的研究
如果替
换
的字符串包含字符
'{'
,那么
f
字符串就会
报错
?
use_input_string= 'Test string {'
print(f'Test- {use_input_string}'.format())
这段代码会报错
:
ValueError:Single '{' encountered in format string
那我们是否需要验证用户输入的内容,然后拒绝用户输入的左大括号呢?是否有办法能够避免这个错误呢?
先不要向下翻,自己想一想这个问题?
先在自己心中想出一个自己觉得对的答案。
或者你实在是想不出来了
......
那么马上要公布答案了哦
~~
公布答案
f
字符串是隐式格式化的,也就是说你不需要调用
format
方法。这里调用
format
方法,相当于进行了两次格式化。实际上题主想要的正确代码应该是
use_input_string= 'Test string {'
print(f'Test- {use_input_string}')
我们画蛇添足地在
f
字符串后面又增加了一个
format
调用,就成了对
f
字符串格式化后的结果再次进行格式化了。也就是相当于这句
print('Test- {use_input_string}'.format())
自然地就报错了。
最后,我们用一段代码总结一下本题。
>>>use_input_string = 'Test string {'
>>>print(f'Test - {use_input_string}'.format())
Traceback(most recent call last):
File "<stdin>", line 1, in<module>
ValueError:Single '{' encountered in format string
>>>print(f'Test - {use_input_string}')
Test - Test string {
更多免费技术资料可关注:annalin1203