您的位置:首页 > 编程语言 > Python开发

【Python】 字符串的相关小知识点

2017-04-12 15:52 141 查看
字符串

  很久以前,刚接触IT知识的时候,我觉得字符串还有字符变量是很奇葩的存在。数字,数组,字典什么的这些数据类型要不就是自然界固有的要不就是为了计算方便而发明出来的一些数据的组合方式。但是字符串这玩意儿的存在很突兀,它既不是自然界固有的(在人类发明创造的语言中才有意义)也不是一种很NB的数据结构。后来才慢慢意识到,字符串为什么重要,因为人始终还是要看字符串的呀!字符串这个数据类型,可以说是一个机器语言和人类语言之间的一个interpreter。有它在人类才能看懂机器的输出不是。

  恩。。扯远了,这篇里不讲逻辑上字符串该怎么用(http://www.cnblogs.com/franknihao/p/6616635.html),也不讲编码什么的(http://www.cnblogs.com/franknihao/p/6557559.html)而是主要聚焦在python中字符串的书写方法,以及一些乱七八糟的知识上。可以算是一篇字符串专题的零碎把= =因为字符串这玩意儿用得太频繁了,经常会遇到问题。。

■  关于单引号和双引号的区别

  python中用双引号和单引号都可以表示字符串,但是它们并不是什么时候都可以乱用的。

  单纯地表示一个字符串比如helloworld的话,确实s = "helloworld"和s = 'helloworld'是一样的。但是当字符串本身带有引号(单引号或双引号)的时候情况就不一样了。比如我要print出来的结果是I say "hello"的话,在语句里如果用双引号写那么内容中的双引号就要转义了: s = "I say \"hello\"",但是如果用单引号写就不用: s = 'I say "hello"'。到底是用单引号还是双引号主要还是看个人习惯。同样的,如果是I say 'hello'也是一样的,这样的话就是语句中用单引号要转义,双引号不用。那么可不可以在双引号串里面写单引号转义呢?答案也是可以的,python会对标识要转义的部分进行转义操作。也就是说s = "'"和s = "\'"print出来之后都是一个单引号。

  这是针对单引号和双引号的转义,对于其他的转义字符,比如\\来表示一个反斜杠,是一样的

■  关于字符串前缀

  众所周知,python的字符串前可以加上r,u之类的前缀。

  前面加上u的字符串,意思是这个字符串应不进行其他编码而直接以unicode码存到内存中。对于字符串,尤其是非纯ascii字符串,默认情况下python都是按照前面几行的# coding=xxx指定的编码来存储字符串的。如果是前缀了u的话,那么就不管这个编码是什么,都按照unicode的编码来存储字符串。以unicode存储的好处在于在不同环境中可以根据不同的编码来进行不同的encode。

  前缀r的意思是raw。从一个实例来看:

>>>s = "\t"
>>>k = r"\t"
>>>s
'\t'
>>>print s

>>>k
'\\t'
>>>print k
\t


  一般字符串在储存时不会做任何处理,写出来的是什么存进内存的就是什么,这就导致在print的时候如果字符串中含有可转义的字符的话就会被转义掉。但raw的字符串在储存时会对字符串的可转义字符进行反转义,所以引号里写什么print出来的就是什么。(这个和repr不一样,repr真的是写什么就print什么,连引号都会print出来)。从功能上来说,加不加r其实是解决字符串歧义的问题的,因为python不知道你写下这串字符串,是真的想要这串字符串呢还是想让他有个转义的呢?所以增加了r这个功能。另外再插两句话,

  1. 当反斜杠后面跟着的字符和反斜杠不形成转义字符的话,那么python其实就可以断定你是想在print出来的时候结果中有反斜杠的,所以在存进内存的时候python会对这个反斜杠自动做反转义,不管你是否加了r:

>>>s = "a\.b"
>>>s
'a\\.b'
>>>k = r"a\.b"
>>>k
'a\\.b'
#两者的结果是一样的,前者是python自动为用户反转义的结果
>>> s = "a\\.b"
>>>s
'a\\.b'
#这种是比较标准的写法,因为如果希望在print结果中有一个反斜杠,确实应该在原文中写两个反斜杠
>>>k = r"a\\.b"
>>>k
'a\\\\.b'
#由于前面加了r,所以存进内存时被反转义成四个反斜杠的样子,这样print出来才能有两个反斜杠


  2. python无法处理r"\",因为解释器会把这个解释成一个内含一个转义双引号的字符串,所以会报SyntaxError说明引号没有成对出现。所以在python中,如果期望print出来是一个反斜杠,那么就一定要写"\\",不能有r前缀的。(顺便r"\\"在内存中就是四条反斜杠了)

■   unicode-escape是什么编码

  今天碰到了个没见过的玩意儿。一个字符串s居然用了s.decode('unicode-escape')这样的操作。unicode-escape显然和utf-8,gbk这些编码格式不一样。

  搜了下,发现这个编码的作用主要是这样的:

  如果有s = u'\u4f60\u597d',我们知道s是一个unicode类型。实际上在u'xxx'的xxx中,\u是会被解释成声明unicode编码,因此print s的时候会显示编码处理过后的内容。这里具体是“你好”两个汉字。

  但是如果一不小心,字符串前面的类型声明u忘记写了,变成了s = '\u4f60\u597d'(或者'\\u4f60\\u597d',\u在一般字符串中没有转义解释,所以加不加两个斜杠都一样)的话。此时\u会被按照一般的字符解释,所以print出来的就是\u4f60\u597d。一般我们会想到是不是可以unicode(s)把它强行转换成unicode类型,但是实验证明此时解释器仍然把s作为一个完整的字符串解释。

  此时就要用到unicode-escape了,即s.decode('unicode-escape'),之后,s就又变回了unicode类型的u'\u4f60\u597d'。同理,如果就是想把一个unicode给整成\uxxx形式的字符串,那么就encode('unicode-escape')就行了。

  那么这个功能可能在哪里用到呢。比如非常常用的json.dumps方法,dumps方法会默认用默认的编码格式utf-8将所有字符串都decode成unicode(当然如果字符串是gbk之类的编码就会报错decodeerror)。比如:

# -*- coding:utf-8 -*-
import json

print repr(json.dumps({'a': '你好'}))
# 输出是'{"a": "\\u4f60\\u597d"}'


  但是如果固定传输时字符串的编码要是指定的比如utf-8,此时我们传送的这个就不符合要求了。那么就可以 json.dumps({'a': '你好'}).decode('unicode-escape').encode('utf-8'),此时再看下,输出中中文字符的部分就变成了\x86\xa3之类的了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: