原载于https://mp.weixin.qq.com/s/8cdvlSUsIJn94TLNOkHclg
字符串是常用的一种数据类型。在python里面,可以直接处理的字符类型有string和unicode。
string类型存储的是单字节的字符流,string类型在处理字符串的时候是单个字节单个字节进行处理的,因此string类型可以表示的编码只有ascii编码,也就是我们常见的字母和数字、符号等字符。string类型在存储utf8、gbk,gb2312等多字节的编码的时候,是按照字节流的方式来存储的。string类型并不知道几个字节表示一个字符,也不知道从哪个位置开始解析一个字符。
unicode存储的是双字节甚至多字节的unicode编码,unicode类型在处理字符串的时候取双个字节进行处理,现在unicode扩容有些字符甚至取四个字节进行处理,因此unicode类型可以表示世界上所有的字符。
在实际应用当中,string类型可以用来存储utf8、gbk等编码的字节流,而unicode类型则是用来作为处理非英文字符的中间类型暂时存在。在处理中文字符的时候,如果能够严格养成习惯,先把字节流转化为unicode进行处理,处理完毕之后再转化为想要的编码字节流,那么就不会产生乱码等情况。
不过现在很多人都不会按照这个步骤来做,这样也不是不能做,把python的编译环境以及python文件的保存编码配合好,也能偷个懒。不过河边走多了也会湿鞋,如果不是非常确定自己所处理的字符编码是哪一种,就必须得面对在同一个python代码中处理多种字符编码的复杂状况。
像上交所的网页,就是utf8;深交所的网页,全是gbk;而新浪的新闻和研报等等,多数是gb2312。很多人以为设置默认编码为utf8就万事大吉,如此嫌麻烦而造成的麻烦是会以指数级增长的。中文网站的编码环境远比其它语言来的复杂,既有utf8等国际通用的标准,也有gb18030等国家标准,中间一点没有衔接好,读出的就是乱码了。
字符串的基本操作其实和tuple差不多,字符串类型实际上是一个字节序列,是一个不可变的变量。字符串最重头的,大概就是中文环境下复杂的编码问题了。
下面还是一步一步探讨一下字符串的常用知识点吧。
7.1 string的基本操作
要生成string字符串,可以直接用'',或者""把字符串括起来就可以。
>>> s='abcde'
>>> s
'abcde'
>>>s="abcde"
>>> s
'abcde'
这时会产生一个问题,如果''括起来的字符串包含了'该怎么办。这时需要引入一个\转义字符,当碰到了\,就知道后面的那个字符有别的意义。在这里\可以对'进行转义,这样就不会被当作字符串结尾。
>>> s='abc\'de'>>> print(s)abc'de
\转义字符后面跟不同的字符,会有特殊的含义。比如\t是tab效果,\r\n是回车换行的效果。
>>> s='abc\ted'
>>> print(s)
abc ed
>>> s='abc\r\nde'
>>> print(s)
abc
de
如果想要取消所有的转义,使用r操作,那么整个字符串就是字符串的字面意思。
>>> s=r'abc\'de'
>>> print(s)
abc\'de
使用'''可以定义一个多行的字符串。
>>> s='''
... 1.xxx
... 2.###
... 3.***
... '''
>>> print(s)
1.xxx
2.###
3.***
>>> s
'\n1.xxx\n2.###\n3.***\n'
上面的代码中,把字符串打印出来可以发现,'''操作往每行数据中加入\n换行符。
上面提到string是一个字符序列,因此可以使用序号和切片操作来获取单个字符或者子字符串。
>>> s='abcde'
>>> s[1]
'b'
>>> s[:3]
'abc'
上面也提到了string是一个不可变变量,因此不能对string进行修改。
>>> s[0]='g'
Traceback (most recent calllast):
File "<stdin>", line 1, in<module>
TypeError: 'str' object doesnot support item assignment
两个字符串可以直接连接生成一个新的字符串,就像tuple一样。
>>> s1='abc'
>>> s2='de'
>>> s1+s2
'abcde'
使用str()函数可以把其他类型转化成字符串类型。
>>> str(11)
'11'
使用len()函数可以获取字符串的长度
>>> s='abcde'
>>> len(s)
5
7.2 unicode的基本操作
使用u操作,可以生成unicode字符串。
>>> s=u'中文'
>>> s
u'\u4e2d\u6587'
如果不需要任何转义,则用ur操作,和string类型的r操作效果一致。
7.3 字符编码处理的简单介绍
在上面说到,string类型存储了不同编码的字节流,在处理的时候一般需要把它转化成unicode编码进行处理,然后再转化为想要的编码。把string类型存储的字节流变成unicode,需要用decode,而处理完了之后使用encode把unicide变成需要的编码。
比如说’中’字的gbk编码是d6d0,一个字需要两个字节来表示,一个是\xd6,一个是\xd0。\x的意思是16进制。
此时把这个字符串进行decode,参数是gbk。就会把它转化成中间编码unicode。而对这个unicode进行encode,参数是gbk,又会把它转化为gbk编码。
以下的代码片段就展示了一个string类型的字节流,通过decode变成unicode,一个unicode类型字符串,通过encode又变回一个gbk编码的string类型的字节流的过程。
>>> s='\xd6\xd0'
>>> s.decode('gbk')
u'\u4e2d'
>>>s1=s.decode('gbk')
>>> s1.encode('gbk')
'\xd6\xd0'
字符编码的问题还涉及到python编译环境的默认编码,python文件保存的字符编码,python所在操作系统的文件路径的字符编码。这些问题都会在后续章节中讲解。
7.4 string和unicode的常用方法
string和unicode有一些常用的方法,可以更好地处理字符串。比如说查找子串、判断是否数字、替换字符串、分隔字符串、连接字符串等。这些操作是经常用到的。
find()方法,可以在字符串里查找子串。如果能够找到,就返回在字符串中的序号;如果没有找到,就返回-1。
>>> s='abcda'
>>> s.find('b')
1
>>> s.find('g')
-1
>>> s.find('da')
3
>>> s=u'中文字符中的字符'
>>> s.find(u'符')
3
isdigit()可以用来判断字符串是不是全是数字。要注意的是,小数并非全数字。
>>> s='123'
>>> s.isdigit()
True
>>> s='1.23'
>>> s.isdigit()
False
replace()可以把某些字符串替换掉。
>>>s='abcdedfabcdef'
>>>s.replace('ab','12')
'12cdedf12cdef'
split()可以按照分隔符把字符串分开。
>>>s='abcdedfabcdef'
>>> s.split('ab')
['', 'cdedf', 'cdef']
join()可以把字符串列表里面的所有字符串连接起来。
>>>stringlist=['a','b','c']
>>>''.join(stringlist)
'abc'
本来想把格式化也写完了,不知道为什么浏览器崩溃了多次。算了下次吧。本文完。