str - 字符串

Page content

关于编码

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”,各个字符的索引位置如下:

str slice

忽略起始值 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.isdecimal() ==> 如果 s 非空,并且每个字符都是 10 进制的数字[1]1

  • str.isdigit() ==> 如果 s 非空,并且每个字符都是数字[1]1

  • str.isnumeric() ==> 如果 s 非空,并且每个字符都是数字[1]1

  • 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 格式。


Python 3.x 标准库笔记