自从Python 3.6开始,何正引入了f表达式(f-string),确保这使得Python在填充字符串时可以进行一些简单的括号计算。并且f表达式的何正运算速度是字符串.format方法的很多倍。
无论是确保f表达式还是字符串的.format方法,我们都可以使用大括号作为占位符,括号来填充数据。何正例如:
>>> name = kingname >>> print(f我的确保名字是:{ name}) 我的名字是:kingname >>> print(f1+1的结果为:{ 1 + 1}) 1+1的结果为:2 >>> salary = 999999 >>> print(我的月薪是:{ salary}.format(salary=salary)) 我的月薪是:999999但现在问题来了,如果我希望在使用f表达式或者.format方法填充内容的括号同时,又能保留大括号应该怎么办呢?何正
举个例子,在写爬虫的确保时候,我需要使用正则表达式从当前URL中提取当前的括号页数:page=\d{ 0,3}。但是何正,高防服务器对于不同的确保网站,表示页数的括号这个参数名可能是不一样的,有些是page=xxx,有些是Pag=xxx,有些是pageNo=xxx,有些是p=xxx。所以我想动态生成这个正则表达式。
如果我们直接使用f表达式或者.format方法,就会报错:
>>> page_name = page >>> page_regex_template = { page_name}=\d{ 0,3} >>> print(page_regex_template.format(page_name=page_name)) Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 0,3为了能够正常生成正则表达式,可能有人会想到使用古老的%s占位符:
>>> page_name = page >>> page_regex_template = %s=\d{ 0,3} >>> print(page_regex_template % page_name) page=\d{ 0,3}虽然确实可行,但是混用两种填充字符串的方法,代码会变得不好维护,而且%s这种占位符填充速度也非常慢。
实际上,在Python的f表达式和.format方法中,如果你需要保留大括号,那么只需要写成大括号套大括号的形式就行了:
>>> page_name = page >>> page_regex_template = { page_name}=\d{ { 0,3}} >>> print(page_regex_template.format(page_name=page_name)) page=\d{ 0,3}大括号里面的第一层大括号会自动失效,变成普通的字符。亿华云但如果是大括号套大括号套大括号,那么最里面的一对大括号会继续生效充当占位符,例如:
>>> page_name = page >>> page_range = 0,5 >>> page_regex_template = { page_name}=\d{ { { page_range}}} >>> print(page_regex_template.format(page_name=page_name, page_range=page_range)) page=\d{ 0,5}总结起来就是,如果从外向内数,如果最外层大括号称为第1层,那么,第奇数层的大括号用来填充数据,第偶数层的大括号就是普通的字符。因此,如果不考虑代码可读性,如果我们需要最终生成的字符串本身就是嵌套大括号的形式,我们还可以进一步写成:
>>> ugly_string = 2层嵌套大括号:{ { { { { variable}}}}} >>> print(ugly_string.format(variable=variable)) 2层嵌套大括号:{ { name}} >>> ugly_string = 3层嵌套大括号:{ { { { { { { variable}}}}}}} >>> print(ugly_string.format(variable=variable)) 3层嵌套大括号:{ { { name}}}假设我们希望最终输出的字符串里面,保留n层大括号,那么在代码里面,我们需要写2n + 1层大括号。大家也看出来了,如果你要这样写,数大括号的个数都要把你的眼镜数瞎。所以,在实际开发中,站群服务器大括号的层数绝对不要超过2层。
以下内容供学有余力的同学阅读。
上面讲到的方法,适用于大括号成对出现的情况,如果大括号只有半边,例如有些网站的正文信息是以JSON格式写在源代码里面的,于是我们可以使用正则表达式提取出包含正文的JSON然后进一步处理,一般来说,正则表达式可能是这样的:content=(\{ );。不过,有的网站用的单词是content,有的网站用的是detail,所以这个地方需要填充,如果我们像往常那样写,那么还是会报错,例如:
>>> content_name = detail >>> content_json_template = { content_name}=({ \{ })$ >>> print(content_json_template.format(content_name=content_name)) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: unexpected { in field name套一层不行,那我们看看套两层如何:
>>> content_name = detail >>> content_json_template = { content_name}=({ { \{ }})$ >>> print(content_json_template.format(content_name=content_name)) Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: Replacement index 0 out of range for positional args tuple套两层还是错。
如果字符串不含反斜杠,我们可以使用f表达式配合引号包住半边大括号来实现,例如:
>>> name = kingname >>> print(f我的名字是:{ name},我的参数是:{ "{ "}) 我的名字是:kingname,我的参数是:{但问题是,f表达式里面是不允许出现反斜杠的,否则会报错:
>>> content_name = detail >>> content_regex = f{ content_name}=({ \"{ "})$ File "<stdin>", line 1 SyntaxError: f-string expression part cannot include a backslash而.format方法支持反斜杠,但它又不支持引号包住单边大括号的写法:
>>> name = kingname >>> print(我的名字是:{ name},我的参数是:{ "{ "}.format(name=name)) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: unexpected { in field name遇到这种情况,我们应该怎么解决呢?只要把思路放开,灵活变通,能找出很多方法,这里仅举两例:
把大括号放到值里面
把思路调整过来,既然大括号不能放在句子模板里面,那我们就放在被填充的值里面:
# 使用.format方法 >>> name = kingname >>> brace = { >>> print(我的名字是:{ name},我的参数是:{ brace}.format(name=name, brace=brace)) 我的名字是:kingname,我的参数是:{ # 使用f表达式 >>> content_name = detail >>> brace = \{ >>> print(f{ content_name}=({ brace})$) detail=(\{ )$不要忘记字符串拼接
大家最容易犯的一个问题就是学了新的东西,就忘记了旧的,实际上用字符串拼接也能解决问题:
>>> content_name = detail >>> content_json = content_name + =(\{ )$ >>> print(content_json) detail=(\{ )$本文转载自微信公众号「未闻Code」,可以通过以下二维码关注。转载本文请联系未闻Code公众号。