在公众号粉丝群里面,经常有同学问类似下面这样的问题:
而当他发出来这个图,我就知道他想问什么问题了,所以直接给出了答案:把反斜杠删了。
为什么有人会问出这样的问题?为什么我可以毫不犹豫的知道 删除反斜杠没有任何不良影响?这就要从 Python 的单引号、双引号、三引号说起了。
在 Python 里面,单引号和双引号的作用是完全一样的。当我们要定义一个字符串的时候,使用单引号和双引号没有任何区别:
- # 下面两种写法完全相同
- a = 'kingname'
- b = "kingname"
那在什么情况下应该用单引号,什么情况下应该用双引号呢?那就是在字符串里面本来就有单引号的时候,最外面就用双引号;字符串里面本来就有双引号的时候,最外面就有单引号:
- a = 'kingname says: "yes".'
- b = "kingname syas: 'yes'."
那么如果我想定义的字符串里面本来就既有单引号又有双引号怎么办呢?那么我们可以用三单引号。
- a = '''青南说: '单引号'比"双引号"更好看'''
当然,还有三双引号,它的功能跟三单引号完全相同,但是在 PEP8规范里面,三双引号一般用来写函数文档型注释,所以一般多行字符串我们不会使用三双引号。如下图所示:
requests 源代码
顺带一提,Requests的代码写得非常规范,当你不知道怎么写代码才优雅的时候,你就去参考 Requests 的源代码。它怎么写,你就怎么写。
但我们知道,三单引号是给多行字符串使用的,如果你觉得短短几个字符的字符串,就因为含有双引号或者单引号,你就要搬出三单引号,未免杀鸡用牛刀,那么,你还可以使用反斜杠。例如:
- a = 'kingname says: \'yes\'.'
- b = "kingname says: \"yes\"."
- c = '青南说: \'单引号\'比"双引号"更好看'
- d = "青南说: '单引号'比\"双引号\"更好看"
也就是说,如果你字符串最外面使用的是单引号,那么你可以在字符串里面自带的单引号前面加上反斜杠;如果你字符串最外面使用的是双引号,那么你可以在字符串里面自带的双引号前面加上反斜杠。
本文开头的这个同学,他发的截图是这样的:
可以看到,它的字典中,content的值是使用三双引号包起来的,所以,值里面的单引号没有必要加上反斜杠。
大家可能会觉得非常奇怪,上面这些规则,看起来都是显而易见的,怎么可能有人会搞混呢?实际上,事情真的没有你想的那么简单。有两个场景会让你出问题。
场景1,在 PyCharm 的调试模式中。当我们定义一个字符串的时候,调试窗口里面显示的字符串变量总是使用单引号包裹的,如下图所示:
无论在代码里面,我定义字符的时候使用的是单引号还是双引号,在调试窗口里面始终都是单引号。那么,如果我定义的字符串包含了单引号,此时在调试窗口里面一定会出现反斜杠:
图中只有两行代码,你可以很好鉴别。但是如果你是在调试别人的代码,看到了一个字符串里面出现了反斜杠,你不一定能反应过来单引号前面的反斜杠是这样来的。当你自己使用三引号或者双引号包裹这样一段字符串的时候,你是可以直接删除这个反斜杠的。
场景2,在 JSON 中。JSON 的Key 和 Value 都是使用双引号包裹的,如下图所示:
如果你的字符串里面原本就有双引号,那么,无论你在代码里面定义的时候怎么写,最终打印出来的 JSON 字符串中一定有反斜杠:
有些同学在写爬虫的时候,抓目标网站的 API 接口,看到返回的 JSON 字符串里面有反斜杠,想都不想,反手一个.replace把所有反斜杠全部替换成空。这种做法显然是错误的。
当你发现网站返回的数据是 JSON 字符串的时候,你应该首先传入json.loads把它解析一遍,然后再来看数据内容长什么样。并且,解析了以后,如果你使用 PyCharm 的调试模式来看,那么你还需要注意上面场景1的情况。例如下面这个 JSON 字符串,就是两种情况的结合。
- {
- "sentence": "\u4eca\u5929\u6211\u4eec\u5b66\u4e60\u82f1\u6587\u53cc\u5f15\u53f7\\"\u548c\u82f1\u6587\u5355\u5f15\u53f7'\u7684\u4f7f\u7528",
- "address": "\u4e0a\u6d77"
- }
这个 JSON 字符串里面有非常多的反斜杠,很多人看到这个就很想去把这些反斜杠全部转成空字符串。但实际上,你只需要使用json.loads处理一下,信息马上就正常了,如下图所示:
但即便如此,如果你试图用调试模式去查看解析以后的值,你会发现里面还是有反斜杠,因为里面有单引号。
最后,考大家两个个问题:图片
上面这段代码,已知b['sentence'][17]对应了单引号的号字。那么这段代码最后会打印出什么字符?
如果我们在调试模式,在第10行打一个断点,然后通过Evaluate功能执行代码片段b['sentence'][18],下面的 result又是什么?
本文转载自微信公众号「未闻Code」,可以通过以下二维码关注。转载本文请联系未闻Code公众号。