最近也在一个视频网站的爬虫,项目已经完成,中间有不少需要总结的经验。

从Python 3.6开始,f-Strings是格式化字符串的一种很棒的新方法。与其他格式化方式相比,它们不仅更具可读性,更简洁且不易出错,而且速度更快!

Python中的“老式”字符串格式化

在Python 3.6之前,你有两种主要的方式,将Python表达式嵌入到字符串文字中进行格式化:%-formatting和str.format()。本文将首先介绍如何使用它们以及它们的局限性。

选项#1:%-formatting

这是Python格式化的OG,从一开始就存在于语言中。你可以在Python文档中阅读更多内容。请记住,文档不建议使用%格式,其中包含以下注意事项:

“这里描述的格式化操作表现出各种古怪问题,导致许多错误(例如未能正确显示元组和字典)。

使用较新的格式化字符串文字或str.format()方法有助于避免这些错误。这些替代方案还提供了更强大,灵活和可扩展的文本格式设置方法。”

如何使用 %-formatting

字符串对象具有使用该%运算符的内置操作,可用于格式化字符串。这是实际的情况:

>>> name = "Eric"
>>> "Hello, %s." % name
'Hello, Eric.' 

为了插入多个变量,你必须使用这些变量的元组。这是你要执行的操作:

>>> name = "Eric"
>>> age = 74
>>> "Hello, %s. You are %s." % (name, age)
'Hello Eric. You are 74.' 

为什么%-formatting不好

上面看到的代码示例具有足够的可读性。但是,一旦开始使用多个参数和更长的字符串,你的代码将很快变得不那么易读。看起来有些混乱:

>>> first_name = "Eric"
>>> last_name = "Idle"
>>> age = 74
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> "Hello, %s %s. You are %s. You are a %s. You were a member of %s." % (first_name, last_name, age, profession, affiliation)
'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.' 

这种格式不是很好,因为它很冗长并且会导致错误,例如不能正确显示元组或字典。

选项#2:str.format()

Python 2.6中引入了这种完成工作的新方法。你可以查看《 Python字符串格式新手指南》以获取更多信息。

如何使用str.format()

str.format() 是对 %-formatting 的改进。它使用正常的函数调用语法,并且可以通过 format() 方法对被转换为字符串的对象进行扩展。

使用str.format(),替换字段用花括号标记:

>>> "Hello, {}. You are {}.".format(name, age)
'Hello, Eric. You are 74.' 

你可以通过引用变量的索引以任何顺序引用它们:

>>> "Hello, {1}. You are {0}.".format(age, name)
'Hello, Eric. You are 74.' 

但是,如果你插入变量名,则会获得以下额外的好处:能够传递对象,然后在花括号之间引用参数和方法:

>>> person = {'name': 'Eric', 'age': 74}
>>> "Hello, {name}. You are {age}.".format(name=person['name'], age=person['age'])
'Hello, Eric. You are 74.' 

你也可以使用**字典来完成这个巧妙的技巧:

>>> person = {'name': 'Eric', 'age': 74}
>>> "Hello, {name}. You are {age}.".format(**person)
'Hello, Eric. You are 74.' 

str.format() 与%格式相比绝对是一个升级。

为什么 str.format() 不好

使用str.format()代码比使用 %-formatting 的代码更容易阅读,但是str.format()当你处理多个参数和更长的字符串时,代码仍然很冗长。看看这个:

>>> first_name = "Eric"
>>> last_name = "Idle"
>>> age = 74
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> print(("Hello, {first_name} {last_name}. You are {age}. " + 
>>>        "You are a {profession}. You were a member of {affiliation}.") >>>        .format(first_name=first_name, last_name=last_name, age=age, >>>                profession=profession, affiliation=affiliation))
'Hello, Eric Idle. You are 74. You are a comedian. You were a member of Monty Python.' 

如果你要.format()在字典中传递变量,则可以将其解压缩.format(**some_dict)并按字符串中的键引用值,但是必须有一种更好的方法来执行此操作。

f-Strings表达式:Python中一种增强的格式化字符串的新方法

f-Strings 表达式使格式化更容易。他们加入了Python 3.6。你可以在2015年8月由Eric V.Smith撰写的PEP 498中阅读全部内容。

f-Strings 也称为“格式化的字符串文字”,是一种字符串文字,其开头是 f,后面是大括号,其中包含将被替换为其值的表达式。这些表达式在运行时被评估,然后使用 "format" 协议进行格式化。当你想了解更多信息时,Python文档是你的朋友。

下面是一些 f-strings 可以让你的生活更轻松的方法。

简单语法

看看这是多么容易阅读:

>>> name = "Eric"
>>> age = 74
>>> f"Hello, {name}. You are {age}."
'Hello, Eric. You are 74.' 

使用大写字母也是有效的F

>>> F"Hello, {name}. You are {age}."
'Hello, Eric. You are 74.' 

任意表达

因为 f-strings 在运行时被评估,所以您可以在其中放入任何和所有有效的 Python 表达式。

你可以做一些非常简单的事情,例如:

>>> f"{2 * 37}"
'74' 

但是你也可以调用函数。这是一个例子:

>>> def to_lowercase(input):
...     return input.lower()

>>> name = "Eric Idle"
>>> f"{to_lowercase(name)} is funny."
'eric idle is funny.' 

你还可以选择直接调用方法:

>>> f"{name.lower()} is funny."
'eric idle is funny.' 

你甚至可以使用从带有f-strings的类创建的对象:

class Comedian:
    def __init__(self, first_name, last_name, age):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age

    def __str__(self):
        return f"{self.first_name} {self.last_name} is {self.age}."

    def __repr__(self):
        return f"{self.first_name} {self.last_name} is {self.age}. Surprise!" 

你执行以下操作:

>>> new_comedian = Comedian("Eric", "Idle", "74")
>>> f"{new_comedian}"
'Eric Idle is 74.' 

__str__()__repr__()方法处理对象是如何呈现为字符串,所以你需要确保你包括你的类定义这些方法的至少一个。如果你必须选择一个,请继续使用,__repr__()因为它可以代替使用__str__()

返回的__str__()字符串是对象的非正式字符串表示形式。返回的字符串__repr__()是正式表示形式,应明确。调用str()repr()比直接使用__str__()和更可取__repr__()

默认情况下,f字符串将使用__str__(),但是如果你加入转换标志 !r,你可以确保它们使用__repr__()

>>> f"{new_comedian}"
'Eric Idle is 74.'
>>> f"{new_comedian!r}"
'Eric Idle is 74. Surprise!' 

如果你想阅读一些导致 f-Strings 支持完整Python表达式的对话,则可以在此处进行。

多行f-Strings

你可以使用多行字符串:

>>> name = "Eric"
>>> profession = "comedian"
>>> affiliation = "Monty Python"
>>> message = (
...     f"Hi {name}. "
...     f"You are a {profession}. "
...     f"You were in {affiliation}."
... )
>>> message
'Hi Eric. You are a comedian. You were in Monty Python.' 

但是请记住,你需要在多行字符串的每一行前面放一个f。以下代码不起作用:

>>> message = (
...     f"Hi {name}. "
...     "You are a {profession}. "
...     "You were in {affiliation}."
... )
>>> message
'Hi Eric. You are a {profession}. You were in {affiliation}.' 

如果你没有f在每行的前面都放一个,那么你将只有规则的,古老的,花园风格的琴弦,而不是闪亮的,新颖的,奇特的f琴弦。

如果你想将字符串分布在多行中,则还可以选择使用-转义字符 \

>>> message = f"Hi {name}. " ...           f"You are a {profession}. " ...           f"You were in {affiliation}."
...
>>> message
'Hi Eric. You are a comedian. You were in Monty Python.' 

但是,如果使用以下方法,将会发生以下情况"""

>>> message = f"""
...     Hi {name}. 
...     You are a {profession}. 
...     You were in {affiliation}.
... """
...
>>> message
'\n    Hi Eric.\n    You are a comedian.\n    You were in Monty Python.\n' 

阅读PEP 8中的缩进准则。

速度

f-Strings 比 %-formatting 和 str.format() 都要快。如你所见,f-Strings 是在运行时求值的表达式,而不是常量值。以下摘自文档:

“f-Strings 提供了一种使用最小语法在字符串文字中嵌入表达式的方法。应当注意,f-Strings 实际上是在运行时评估的表达式,而不是常数。在Python源代码中,f-Strings 是文字字符串,前缀为f,其中花括号内包含表达式。这些表达式将替换为其值。” (来源)

在运行时,大括号内的表达式在其自己的范围内求值,然后与 f-Strings 的字符串文字部分放在一起。然后返回结果字符串。这就是全部。

这是速度比较:

>>> import timeit
>>> timeit.timeit("""name = "Eric"
... age = 74
... '%s is %s.' % (name, age)""", number = 10000)
0.003324444866599663 
>>> timeit.timeit("""name = "Eric"
... age = 74
... '{} is {}.'.format(name, age)""", number = 10000)
0.004242089427570761 
>>> timeit.timeit("""name = "Eric"
... age = 74
... f'{name} is {age}.'""", number = 10000)
0.0024820892040722242 

如你所见,f-Strings 最快。

但是,情况并非总是如此。首次实施时,它们存在一些速度问题,需要使其速度比更快str.format()。引入了特殊的BUILD_STRING操作码。

Python f-Strings:细节

既然你已经了解了为什么 f-Strings 很棒,我相信你一定要开始使用 f-Strings 。当你冒险进入这个勇敢的新世界时,请牢记以下一些细节。

引号

你可以在表达式内使用各种类型的引号。只要确保你没有在表达式中使用与 f-Strings 相同的引号即可。

该代码将起作用:

>>> f"{'Eric Idle'}"
'Eric Idle' 

该代码也将起作用:

>>> f'{"Eric Idle"}'
'Eric Idle' 

你还可以使用三引号:

>>> f"""Eric Idle"""
'Eric Idle' 
>>> f'''Eric Idle'''
'Eric Idle' 

如果发现需要在字符串的内部和外部使用相同类型的引号,则可以使用 \ 命令进行转义:

>>> f"The \"comedian\" is {name}, aged {age}."
'The "comedian" is Eric Idle, aged 74.' 

字典

说到引号,使用字典时要当心。如果要对字典的键使用单引号,请记住确保对包含键的 f-Strings 使用双引号。

这将起作用:

>>> comedian = {'name': 'Eric Idle', 'age': 74}
>>> f"The comedian is {comedian['name']}, aged {comedian['age']}."
The comedian is Eric Idle, aged 74. 

但这是一个语法错误的情况:

>>> comedian = {'name': 'Eric Idle', 'age': 74}
>>> f'The comedian is {comedian['name']}, aged {comedian['age']}.'
  File "", line 1
    f'The comedian is {comedian['name']}, aged {comedian['age']}.'
                                    ^
SyntaxError: invalid syntax 

如果在字典键周围使用与在f字符串外部相同的引号类型,则第一个字典键开头的引号将被解释为字符串的结尾。

大括号

为了使大括号出现在字符串中,必须使用双大括号:

>>> f"{{70 + 4}}"
'{70 + 4}' 

请注意,使用三重花括号将导致字符串中只有一个大括号:

>>> f"{{{70 + 4}}}"
'{74}' 

但是,如果使用的括号多于三个,则可以显示更多的括号:

>>> f"{{{{70 + 4}}}}"
'{{70 + 4}}' 

反斜杠

如前所述,你可以在f-string的字符串部分使用反斜杠转义。但是,你不能在f-string的表达式部分使用反斜杠转义:

>>> f"{\"Eric Idle\"}"
  File "", line 1
    f"{\"Eric Idle\"}"
                      ^
SyntaxError: f-string expression part cannot include a backslash 

你可以通过预先计算表达式并在f字符串中使用结果来解决此问题:

>>> name = "Eric Idle"
>>> f"{name}"
'Eric Idle' 

内部注释

表达式中不应包含使用该 # 符号的注释。下面代码,你会看到语法错误:

>>> f"Eric is {2 * 37 #Oh my!}."
  File "", line 1
    f"Eric is {2 * 37 #Oh my!}."
                                ^
SyntaxError: f-string expression part cannot include '#' 

总结

字符串格式化方法在很多项目里面都能用到,实用价值很高。







订阅继续关注,以后会收到更多有趣的文章。

欢迎关注我的个人网站https://www.bianchengvip.com/

本文为“一个火星程序员”原创文章,转载请标明出处

Python 3的f-Strings:增强的字符串格式语法(指南)的更多相关文章

  1. 用Python自动清理电脑内重复文件,只要10行代码(自动脚本)

    给定一个文件夹,使用Python检查给定文件夹下有无文件重复,若存在重复则删除主要涉及的知识点有:os模块综合应用glob模块综合应用利用filecmp模块比较两个文件步骤分析该程序实现的逻辑可以具化为:遍历获取给定文件夹下的所有文件,然后通过嵌套循环两两比较文件是否相同,如果相同则删除后者。实现问......

  2. 解决jupyter加载文件失败的问题

    遇到个小白常见的问题,发现度娘里面没有记录,翻墙谷歌了下,解决问题,在此写个说明。事情起因:在jupyter notebook中导入文件时发生了错误:%load p2_test1.py错误信息:-----------------------------------------------------......

  3. python 爬取知乎回答下的微信8.0状态视频

    微信 8.0 版本更新后,可以设置个人状态,状态里面可以添加火录制视频,很快状态视频就火了,可以看下知乎热榜有没有微信8.0状态沙雕又可爱的视频或图片?[1]。比如我也设置了一个:于是我就想把这些视频下载下来,也玩一玩。本文讲述如何使用 Python 一键下载知乎某个回答下的所有视频。思路:分析知乎......

  4. 删除pandas中产生Unnamed:0列的操作

    我们在数据处理,往往不小心,pandas会“主动”加上行和列的名称,我现在就遇到了这个问题。这个是pandas中to_csv生成的数据各种拼接之后的最终数据(默认参数,index=True,column=True)Unnamed: 0 ip Unnamed: 0.1 ... 766 767 ......

  5. Python-zip()函数

    Python-zip()函数的一些相关知识Python内置help()的解释返回一个元组迭代器,其中第i个元组包含每个参数序列或可迭代对象中的第i个元素。当最短的可迭代输入耗尽时,迭代器将停止。使用单个可迭代参数,它将返回1元组的迭代器。没有参数,它将返回一个空的迭代器。 功能演示uppercase......

  6. python 合并列表的八种方法

    Python 语言里有许多(而且是越来越多)的高级特性,是 Python 发烧友们非常喜欢的。在这些人的眼里,能够写出那些一般开发者看不懂的高级特性,就是高手,就是大神。但你要知道,在团队合作里,炫技是大忌。为什么这么说呢?我说下自己的看法:越简洁的代码,越清晰的逻辑,就越不容易出错;在团队合作中,......

  7. python中编写函数并调用的知识点总结

    能够调用自己编写的函数,这在很多开发语言中,都会用到一个叫做mian的主函数,这个函数一般都是程序的入口,当程序启动时,首先执行这个函数。在Python中,main函数的主要作用就是你写的模块既可以导入到别的模块中用,也可以在模块本身执行使用。下面就来了解具体使用操作吧。编写简单的函数并调用:def......

  8. Python 打印自己设计的字体的实例讲解

    通过对 26 个字母的设定,设置自己要输出的字体。name = "RUNOOB"# 接收用户输入# name = input("输入你的名字: \n\n") lngth = len(name) l = "" for x in range(0......

  9. Python单元测试框架pytest常用测试报告类型

    先前博客有介绍pytest测试框架的安装及使用,现在来聊聊pytest可以生成哪些测试报告1.allure测试报告关于allure报告参见先前的一篇博文:https://www.cnblogs.com/feng0815/p/13792188.html ,这里不再赘述2.生成resultlog文件#!......

  10. python re模块和正则表达式

    一、re模块和正则表达式先来看一个例子:https://reg.jd.com/reg/person?ReturnUrl=https%3A//www.jd.com/这是京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示。假如我们随意的在手机号码这一栏输入一个11111111111,它会提示我......

随机推荐

  1. 基于Python的接口自动化-读写配置文件

    引言在编写接口自动化测试脚本时,有时我们需要在代码中定义变量并给变量固定的赋值。为了统一管理和操作这些固定的变量,咱们一般会将这些固定的变量以一定规则配置到指定的配置文件中,后续需要用到这些变量和变量值时通过代码读取或者写入数据到该配置文件即可,使用配置文件的好处就是不用在程序员写死,可以使程序更灵......

  2. C# 合并和拆分PDF文件

    一、合并和拆分PDF文件的方式 PDF文件使用了工业标准的压缩算法,易于传输与储存。它还是页独立的,一个PDF文件包含一个或多个“页“,可以单独处理各页,特别适合多处理器系统的工作。PDF文件结构主要可以分为四个部分:首部、文件体、交叉引用表、尾部。PDF操作类库非常多,如下图所示,常用的类库有:S......

  3. PHP 非常实用下载远程图片

    /*** 下载远程图片* @param string $url 图片的绝对url* @param string $filepath 文件的完整路径(例如/wwwhttp://www.580doc.com/images/test) ,此函数会自动根据图片url和http头信息确定图片的后缀名* @param string $filename ......

  4. Python列表推导式玩法

    前言列表做为python的基础,是必须学习的语法之一。一些基础的之前已经是反复温习和使用了,今天我们来学习它的进阶版--》列表推导式。列表推导式:优点:是将所有的值一次性加载到内存中,相比于for循环生成的列表执行速度快,并且语法精简,一行代码就完成for循环多行代码所要完成的事情。缺点:代码的可阅......

  5. mysql:如何利用覆盖索引避免回表优化查询

    说到覆盖索引之前,先要了解它的数据结构:B+树。先建个表演示(为了简单,id按顺序建):idname1aa3kl5op8aa10kk11kl14jk16ml17mn18kl19kl22hj24io25vg29jk31jk33rt34ty35yu37rt39rt41ty45qt47ty53qi57gh......

  6. Android 解决WebView多进程崩溃的方法

    问题在android 9.0系统上如果多个进程使用WebView需要使用官方提供的api在子进程中给webview的数据文件夹设置后缀:WebView.setDataDirectorySuffix(suffix);否则将会报出以下错误:Using WebView from more than one......

  7. windows打包脚本出现 /bin/sh^M: 坏的解释器: 没有那个文件或目录 错误

    1.错误描述我在Windows 10 系统下打包dolphinscheduler,上传到centos7解压之后,执行脚本报如下错误:-bash: ./dolphinscheduler-daemon.sh: /bin/sh^M: 坏的解释器: 没有那个文件或目录^M是什么东东,为什么会有^M通过命......

  8. python基于爬虫+django,打造个性化API接口

    简述今天也是同事在做微信小程序的开发,需要音乐接口的测试,可是用网易云的开放接口比较麻烦,也不能进行测试,这里也是和我说了一下,所以就用爬虫写了个简单网易云歌曲URL的爬虫,把数据存入mysql数据库,再利用django封装装了一个简单的API接口,给同事测试使用。原理创建django项目,做好基础......

  9. c#在sqlserver中使用EF框架

    vs2017,sqlserver2017(localdb)调试通过。在sqlserver中创建数据库d1,表t1如下:录入数据如下:在vs新建任意项目,此处以控制台为例。添加数据模型Model1:为了尽量少写代码,选择下图内容(该模式似乎没有迁移问题,挺好的):说明:连接字符串可以在代码中自行设置,......

  10. nodejs事件和事件循环详解

    目录简介nodejs中的事件循环phase详解timerspending callbacksidle, preparepoll轮询checkclose callbackssetTimeout 和 setImmediate的区别两者的共同点unref 和 refprocess.nextTickproc......