str - 字符串
关于编码
Python 3.0 开始,字符串(str)已经完全是 unicode 编码。这与 Python 2.x 完全不一样。
Python 3.x 采用类似 Java 里面的字符串处理模式(我个人认为 Java 在字符编码这方面是做得最好的)。 str 表示 unicode 文本,bytes 表示字节。而且 str 和 unicode 不可以混着使用(在 python 2.x 里面 8-bits 字符是可以和 7-bit 的 bytes 混着使用的)。
str 类似 Java 里面的 String 类,bytes 类似 Java 里面的 byte[]。 Java 里面的 String 和 byte[]的转换是:
`byte[]` <== java.lang.String.getBytes(String charset)
`byte[]` ==> java.lang.String.String(byte[] bytes, String charset)
而在 Python 3.x 里面 str 和 bytes 的转换是:
`bytes` <== str.encode(encoding)
`str` <== bytes.decode(encoding)
或者另外一种方式:
`bytes` <== bytes(str,encoding)
`str` <== str(bytes,encoding)
str 和 bytes 都是不可修改的对象。bytearray 对象是可修改的对象。
Tips:
- str 是 unicode 编码(内存中基础编码应该是 UTF-16/或 UTF-32,待补充)
- 任何时候 str 和 bytes 之间转换都需要强制指定编码,不要依赖于操作系统的默认编码
- str 和 bytes 都是不可修改的对象
- 一种近似的理解是 python 3.x 中的 str 和 python 2.x 中的 unicode 类似,python 3.x 中的 bytes 和 python 2.x 中的 str 类似,但语义不完全一样
基础使用
直接的字符串定义有四种形式:
s='中文'
s="中国"
s="""历史"""
s='''历史'''
通常而已,单双引号的合理使用在转义时非常方便。而在其他语言中要转义双引号还是很麻烦的,例如 java 中的 json 字符串书写就非常痛苦。 而在 python 中,这是非常容易的事情:
s="""{"name":"adyliu","nick":"imxylz","blog":"http://imxylz.com"}"""
另外在 console 中 print()函数会自动输出合适的单引号或者双引号。 也可以使用原始字符串而不需要转义,例如:
s=r'C:\Windows\System32\drivers\etc\hosts'
python 中字符串可以直接使用比较运算,例如:
>>> s1,s2='ok','o'+'k'
>>> s1==s2
True
>>> 'o'<'k'
False
分片
分片操作有三种语法(start/end/step 都必须是整数):
- seq[start]
- seq[start:end]
- seq[start:end:step]
事实上支持分片的类型是 Sequence Type,包括 list,tuple,range 类型,例如 str、bytes 就是 range 类型。 对于字符串 s=“Light ray”,各个字符的索引位置如下:
忽略起始值 start 表示 0,忽略结束值 end 表示结尾。例如:
>>> s="Light ray"
>>> s[0:5]
'Light'
>>> s[1:6]
'ight '
>>> s[:]
'Light ray'
>>> s[:-4]
'Light'
>>> s[6:]
'ray'
>>> s[-3:]
'ray'
>>> s[::2]
'Lgtry'
>>> s[::-2]
'yrtgL'
>>> s[::-1]
'yar thgiL'
在这个例子中,反转字符串可以用: s[::-1]
基本操作
字符串的基本操作有:
- x in s ==> 判断字符串 s 是否包含 x,返回 True/False
- x not in s
- s + t ==> 拼接字符串,组成新的字符串
- sn 或者 ns ==> n 个字符串 s 拼接在一起
- len(s) ==> 字符串长度(unicode 字符数目,不是字节长度)
- min(s) ==> 字符串中最小的字符(unicode 值)
- max(s) ==> 字符串中最大的字符
- s.count(x) ==> 字符串 s 中 x 出现的次数
完整 API 列表
完整的字符串 API 列表:
-
str.capitalize() ==> 首字母大写
-
str.center(width,char) ==> 字符串前后填充,默认用空格填充,填充后长度是 width,如果 s 本身已经超过 width,则不填充。
-
str.endswith(x,start,end) ==> 检测字符串是否以 x 结尾
-
str.startswith(prefix[,start[,end]]) ==> 检测字符串使用以 prefix 开始
-
str.expandtabs([tabsize]) ==> 将字符串中的 tab 使用 8 个(或者指定个数)的空格替换
-
str.find(sub[,start[,end]]) ==> 查找子串的索引位置,找不到会返回-1,类似 Java 中的 indexOf
-
str.rfind(sub[,start[,end]]) ==> 从右侧开始查找子串的索引位置
-
str.index(sub[,start[,end]]) ==> 查找字串的索引位置,和 find 类似,只是找不到会抛出 ValueError 异常
-
str.rindex(sub[,start[,end]]) ==> 从右侧开始查找字串的索引位置
-
str.isalnum() ==> 如果 s 非空,并且每个字符都是字母或者数字,返回 True
-
str.isalpha() ==> 如果 s 非空,并且每个字符都是字母
-
str.isidentifier() ==> 如果 s 非空,并且是一个有效的标识符
-
str.islower() ==> 如果 s 非空,有一个小写字符,并且所有可小些的字符都是小写的
-
str.lower() ==> 字符串转换为小写
-
str.isprintable() ==> 如果 s 非空,并且每个子否都是可打印的,包括空格,但是不包括换行
-
str.isspace() ==> 如果 s 非空,并且每一个字符都是空白字符
-
str.istitle() ==> 如果 s 非空,并且首字母大写
-
str.title() ==> 字符串每个单词首字母大写
-
str.isupper() ==> 如果 s 非空,有一个大写字符,并且所有可大写的字符都是大写的
-
str.upper() ==> 字符串转换为大写
-
str.join(iterable) ==> 将字符串序列以指定字符串连接起来
-
str.ljust(width[,fillchar]) ==> 使用空格或者指定字符(char)来填充的左对齐字符串,类似 str.center()
-
str.rjust(width[,fillchar]) ==> 使用空格或者指定字符(char)来填充的右对齐字符串,类似 str.center()
-
str.partition(sep) ==> 返回 3 个字符串的元组,包括 sep 的左边部分、sep、sep 右边的部分。如果 sep 不存在,则返回 s 与两个空字符串。
-
str.rpartition(sep) ==> 类似 partition(sep),唯一的区别是,如果 sep 不存在,那么返回两个空字符串和 s,这是 s 是第三个元素。
-
str.replace(old,new[,count]) ==> 字符串替换,纯文本替换(非正则表达式),最多替换 count 次数如果有的话
-
str.strip([chars]) ==> 将头尾的空白字符(或者指定字符)去掉,类似 Java 中的 trim()
-
str.rstrip([chars]) ==> 将尾部的空白字符(或者指定字符)去掉
-
str.lstrip([chars]) ==> 将头部的空白字符(或者指定字符)去掉
-
str.split(sep=None,maxsplit=-1) ==> 分隔字符串为字符串列表(默认使用空白符为分隔符)
-
str.rsplit(sep=None,maxsplit=-1) ==> 从右侧开始分隔字符串为字符串列表
-
str.splitlines([keepends]) ==> 使用换行符分隔字符串为字符串列表
-
str.swapcase() ==> 字符串中的大小写交换
-
str.zfill(width) ==> 如果字符串长度不够,那么在开头填充'0’字符以便达到指定长度
str.encode/bytes.decode
再次讨论编码的问题。
str.encode(encoding=‘utf-8’,errors=‘strict’)
将字符串转换为字节时,可选两个参数,encoding 和 errors。默认情况下 encoding 是 utf-8。 对于 errors,默认是’strict’,这表示如果遇到一个不可编码的字节,那么就会抛出 UnicodeError 异常。 最常用的 errors 值为:
- strict: 抛出异常如果编码错误
- replace: 替换不可编码的字节为’?’
- ignore: 忽略不可编码的字节
同样,对于 bytes.decode()和 bytearray.decode()也有这两个参数。意义与 str 类似。
补充
Unicode 内存描述
Python 3.x 在内存中,Unicode 通常以 UCS-2 格式,也就是UTF-16格式来表示前 65535 个字符。也有 USC-4 也就是UTF-32来描述字符的。
如果以 UTF-32 来描述字符,那么就有 1114111 个字符。我们可以通过 sys.maxunicode 来检测:
>>> import sys
>>> sys.maxunicode
1114111
如果输出 1114111 那么就是 USC-4 格式,如果输出 65535 那么就是 USC-2 格式。