首页 > 编程语言 >为什么 Python 的 f-string 可以连接字符串与数字?

为什么 Python 的 f-string 可以连接字符串与数字?

时间:2022-10-14 13:31:08浏览次数:79  
标签:string format Python 666 类型 字符串

本文出自“Python为什么”系列,归档在 Github 上:​​https://github.com/chinesehuazhou/python-whydo​

毫无疑问,Python 是一门强类型语言。强类型语言。强类型语言!(关于强弱类型话题,推荐阅读这篇 ​​技术科普文​​)

这就意味着,不同类型的对象通常需要先做显式地类型转化, 然后才能进行某些操作。

下面以字符串和数字为例,看看强行操作会产生什么结果:

>>> "Python猫" + 666
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

它报类型错误了(TypeError),说字符串只能连接(concatenate)字符串,不能连接 int 类型。 这正是强类型语言的基本约束。

但是,如果我们先把数字“转化”成字符串类型,再执行“+”操作,就不会报错了:

>>> "Python猫" + str(666)
'Python猫666'

上面的这个例子,对读者们来说,应该并不难理解。

由此,我们要引出一个问题:如何在不作显式类型转化的情况下,进行字符串与数字类型的拼接呢?

在《​​详解Python拼接字符串的七种方式​​》这篇文章中,它梳理了七种拼接字符串的写法,我们可以逐个来试验一下。

几种字符串拼接方式:

1、格式化类:%、format()、template

2、拼接类:+、()、join()

3、插值类:f-string

为了节省篇幅,此处直接把可以顺利拼接的 4 种写法罗列如下:

>>> "%s %d" % ("Python猫", 666)
'Python猫 666'

>>> from string import Template
>>> s = Template('${s1}${s2}')
>>> s.safe_substitute(s1='Python猫',s2=666)
'Python猫666'

>>> "Python猫{}".format(666)
'Python猫666'

>>> num = 666
>>> f"Python猫{num}"
'Python猫666'

第一种写法(即 % 格式化)来自古老的 C 语言,其中的“%d”是一个占位符,表示它将要接收一个整数,并格式化成字符串。

第二和第三种写法,它们是第一种写法的升级版,不同的是,它们的占位符是通用型的,不必指定“%s”、“%d”等等明确的类型。这两种写法中,数字类型的参数被传给特定的格式化方法(即 safe_substitute 与 format),在这些方法的内部,它们会作类型转化处理。

可以说,上述三种写法都不难理解,它们的意图都有迹可循。

但是,现在再看看最后一种写法,也就是 f-string 写法,似乎就不是那么明显了。

首先,在字符串内部,它并没有像“%格式化”那样指定占位符的类型;其次,所要拼接的数字并没有作为任何函数的参数来传递。

也就是说,在明面上根本看不出任何要作类型转化的意图。但是,由于我们已知 Python 是强类型语言,已知数字类型绝对不可能直接拼接到字符串里,因此,只能说明 f-string 语法在底层作了某种类型转化的操作!

那么,我们就可以再提出一个新的问题:f-string 语法在处理字符串与数字时,是如何实现数字的类型转化的呢?

也许有的读者会猜想它是调用了内置的 str() 或 repr()(或它们对应的魔术方法__str__() 与 __repr__()),从而实现类型转化,但是,答案并没有如此简单!

f-string 语法是在 Python 3.6 版本引入的。为了省事,我们直接找到 PEP-498 文档,在里面查阅看是否有关于实现原理的线索。

为什么 Python 的 f-string 可以连接字符串与数字?_类型转化

文档地址:​​https://www.python.org/dev/peps/pep-0498​

PEP 里提到,f-string 的语法格式是这样的:

f'<text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> ...'

其中,花括号里的内容就是要作格式化的内容,除去可选的“optional”部分后,“expression”部分就是真正要处理的内容。对应前文的例子,数字 666 就是一个 expression。

expression 会按 __format__ 协议进行格式化,但是并不会直接调用 __format__() 这个方法。

文档上指出,实际的执行过程等效于type(value).__format__(value, format_spec) 或者 ​format(value, format_spec)​

事实上,字符串对象的 foramt() 方法跟 Python 内置的 foramt() 函数,它们都会调用__format__() 魔术方法,所以,f-string 其实是前文中 format() 格式化写法的升级版。

在默认情况下,​​format_spec​​​ 是一个空字符串,而​​format(value, "")​​​ 的效果等同于​​str(value)​​ ,因此,在不指定其它 format_spec 的情况下,可以简单地认为 f-string 就是调用了 str() 来作的类型转化……

至此,我们看到了 f-string 的实现原理,明白了它在拼接字符串与数字时,效果等效于前文的 format() 格式化方法,也等效于使用 str() 进行类型转化。

写在最后:本文属于“​​Python为什么​​​”系列(Python猫出品),该系列主要关注 Python 的语法、设计和发展等话题,以一个个“为什么”式的问题为切入点,试着展现 Python 的迷人魅力。更多精彩文章,请移步 Github 查看,项目地址:​​https://github.com/chinesehuazhou/python-whydo​



标签:string,format,Python,666,类型,字符串
From: https://blog.51cto.com/u_14244765/5756367

相关文章

  • Python爬虫之requests模块了解
    requests模块知识点:掌握headers参数的使用掌握发送带参数的请求掌握headers中携带cookie掌握cookies参数的使用掌握cookieJar的转换方法掌握超时参数timeout的使用掌......
  • Python爬虫之mongodb介绍和安装
    Mongodb的介绍和安装学习目标了解非关系型数据库的优势了解mongodb的安装1.mongodb的介绍1.1什么是mongodbmongodb是一个功能最丰富的NoSQL非关系数据库。由C++语言......
  • Python爬虫之scrapy_splash组件的使用
    scrapy_splash组件的使用学习目标了解scrapy_splash组件的作用了解scrapy_splash组件的使用1.什么是scrapy_splash?scrapy_splash是scrapy的一个组件scrapy-splash加载js......
  • Python爬虫之http协议复习
    http协议复习知识点掌握http以及https的概念和默认端口掌握爬虫关注的请求头和响应头了解常见的响应状态码理解浏览器和爬虫爬取的区别一提起http协议,大家都会想起它是......
  • 三点共圆的计算代码(Python版本)
    已知三点坐标,计算圆心和半径defcalc_circle_center_and_radius(p1,p2,p3):x1=p1.xy1=p1.yz1=p1.zx2=p2.xy2=p2.yz2=p2......
  • python切片;列表增删改查;列表(加乘法);列表表达式
         [开始:结束:步长] 倒序输出 2、列表增删改查(1)append()   一次只能添加一个元素 (2)extend()方法,一次课添加一个可迭代对象   extend()方法的参数必......
  • python-时间操作
    1. 获取当前时间importtime# 获取当前日期时间 返回值:当前日期时间defget_now_time():now=time.localtime()now_time=time.strftime("%Y-%m-......
  • Python人工智能经典算法之线性回归
    1.9k近邻算法总结[**]优点:1.简单有效2.重新训练代价底3.适合类域交叉样本4.适合大样本自动分类缺点:1.惰性学习2......
  • Python爬虫之数据提取概述
    数据提取概述知识点了解响应内容的分类了解xml和html的区别1.响应内容的分类在发送请求获取响应之后,可能存在多种不同类型的响应内容;而且很多时候,我们只需要响应内容中的......
  • Python爬虫之数据提取-selenium定位获取标签对象并提取数据
    selenium提取数据知识点:了解driver对象的常用属性和方法掌握driver对象定位标签元素获取标签对象的方法掌握标签对象提取文本和属性值的方法1.driver对象的常用属性和方......