| 序列操作符 | 作用 |
|---|---|
| seq[ind] | 获得下标为 ind 的元素 |
| seq[ind1:ind2] | 获得下标从 ind1 到 ind2 间的元素集合 |
| seq * expr | 序列重复 expr 次 |
| seq1 + seq2 | 连接序列 seq1 和 seq2 |
| obj in seq | 判断 obj 元素是否包含在 seq 中 |
| obj not in seq | 判断 obj 元素是否不包含在 seq 中 |
这种方式看起来似乎实现了把两个序列内容合并的概念,但是这个操作不是最快或者说最有效的。对字符串来说,这个操作不如把所有的子字符串放到一个列表或可迭代对象中,然后调用一个 join方法来把所有的内容连接在一起节约内存;类似地,对列表来说,我们推荐读者用列表类型的extend()方法来把两个或者多个列表对象合并.当你需要简单地把两个对象的内容合并,或者说不能依赖于可变对象的那些没有返回值(实际上它返回一个 None)的内建方法来完成的时候时,连接操作符还是很方便的一个选择。
当你需要需要一个序列的多份拷贝时,重复操作符非常有用,它的语法如下:
sequence * copies_int
copies_int 必须是一个整数,不能是长整数.像连接操作符一样,该操作符返回一个新的包含多份原对象拷贝的对象。
简单地讲,所谓序列类型就是包含一些顺序排列的对象的一个结构.你可以简单的用方括号加一个下标的方式访问它的每一个元素,或者通过在方括号中用冒号把开始下标和结束下标分开的方式来访问一组连续的元素.
sequence[index]
sequence[starting_index:ending_index]
sequence[starting_index:ending_index:step]
内建函数 list(),str()和 tuple()被用做在各种序列类型之间转换。你可以把它们理解成其他语言里面的类型转换,但是并没有进行任何的转换。这些转换实际上是工厂函数,将对象作为参数,并将其内容(浅)拷贝到新生成的对象中序列类型转换工厂函数
| 函数 | 含义 |
|---|---|
| list(iter) | 把可迭代对象转换为列表 |
| str(obj) | 把 obj 对象转换成字符串(对象的字符串表示法) |
| unicode(obj) | 把对象转换成 Unicode 字符串(使用默认编码) |
| basestring() | 抽象工厂函数,其作用仅仅是为 str 和 unicode 函数提供父类,所以不能被实例化,也不能被调用 |
| tuple(iter) | 把一个可迭代对象转换成一个元组对象 |
序列类型可用的内建函数
| 函数名 | 功能 |
|---|---|
| enumerate(iter) | 接受一个可迭代对象作为参数,返回一个 enumerate 对象(同时也是一个迭代器),该对象生成由 iter每个元素的 index 值和 item值组成的元组(PEP 279) |
| len(seq) | 返回 seq 的长度 |
| max(iter,key=None) or max(arg0,arg1…,key=None) | 返回 iter 或(arg0,arg1,…)中的最大值,如果指定了 key,这个 key 必须是一个可以传给 sort()方法的用于比较的回调函数. |
| min(iter, key=None) or min(arg0, arg1… key=None) | 返回 iter 里面的最小值;或者返回(arg0,arg2,…)里面的最小值;如果指定了 key,这个 key 必须是一个可以传给sort()方法的,用于比较的回调函数. |
| reversed(seq) | 接受一个序列作为参数,返回一个以逆序访问的迭代器(PEP 322) |
| sorted(iter,func=None,key=None,reverse=False) | func,key 和 reverse 的含义跟 list.sort()内建函数的参数含义一样. |
| sum(seq, init=0) | 返 回 seq 和 可 选 参 数 init 的 总 和 , 其 效 果 等 同 于reduce(operator.add,seq,init) |
| zip([it0, it1,… itN]) | 返回一个列表,其第一个元素是 it0,it1,…这些元素的第一个元素组成的一个元组,第二个…,类推 |
>>> zip([1,2,3,4],[2,3,4,5])
[(1, 2), (2, 3), (3, 4), (4, 5)]
>>> for i in enumerate([1,2,3]):
... print i
...
(0, 1)
(1, 2)
(2, 3)
核心提示: 性能
一般来说,从性能的的角度来考虑,把重复操作作为参数放到循环里面进行是非常低效的.
while i < len(myString): print 'character %d is:', myString[i]
上面的循环操作把大把的时间都浪费到了重复计算字符串 myString 的长度上了.每次循环迭代都要运行一次这个函数.如果把这个值做一次保存,我们就可以用更为高效的方式重写我们的循环操作.
length = len(myString) while i < length: print 'character %d is:', myString[i]
Python 的语法允许你在源码中把几个字符串连在一起写,以此来构建新字符串:
>>>f = urllib.urlopen('http://' # protocol
...'localhost' # hostname
...':8000' # port
...'/cgi-bin/friends2.py') # file
如你所想,下面就是 urlopen()方法所得到的真实输入:
>>> 'http://' 'localhost' ':8000' '/cgi-bin/friends2.py'
'http://localhost:8000/cgi-bin/friends2.py'
如果把一个普通字符串和一个 Unicode 字符串做连接处理,Python 会在连接操作前先把普通字符串转化为 Unicode 字符串:
>>> 'Hello' + u' ' + 'World' + u'!'
u'Hello World!'
字符串格式化符号
| 格式化字符 | 转换方式 |
|---|---|
| %c | 转换成字符(ASCII 码值,或者长度为一的字符串) |
| %r | 优先用 repr()函数进行字符串转换 |
| %s | 优先用 str()函数进行字符串转换 |
| %d / %i | 转成有符号十进制数 |
| %u | 转成无符号十进制数 |
| %o | 转成无符号八进制数 |
| %x /%X | (Unsigned)转成无符号十六进制数(x/X 代表转换后的十六进制字符的大小写) |
| %e/%E | 转成科学计数法(e/E 控制输出 e/E) |
| %f/%F | 转成浮点数(小数部分自然截断) |
| %g/%G | %e 和%f/%E 和%F 的简写 |
| %% | 输出% |
格式化操作符辅助指令
| 符号 | 作用 |
|---|---|
| * | 定义宽度或者小数点精度 |
| - | 用做左对齐 |
| + | 在正数前面显示加号( + ) |
| 在正数前面显示空格 | |
| # | 在八进制数前面显示零(‘0’),在十六进制前面显示’0x’或者’0X’(取决于用的是’x’还是’X’) |
| 0 | 显示的数字前面填充‘0’而不是默认的空格 |
| % | ‘%%‘输出一个单一的’%’ |
| (var) | 映射变量(字典参数) |
| m.n | m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话) |
十六进制输出:
>>> "%x" % 108
'6c'
>>>
>>> "%X" % 108
'6C'
>>>
>>> "%#X" % 108
'0X6C'
>>>
>>> "%#x" % 108
'0x6c'
浮点数和科学记数法形式输出:
>>>
>>> '%f' % 1234.567890
'1234.567890'
>>>
>>> '%.2f' % 1234.567890
'1234.57'
>>>
>>> '%E' % 1234.567890
'1.234568E+03'
>>>
>>> '%e' % 1234.567890
'1.234568e+03'
>>>
>>> '%g' % 1234.567890
'1234.57'
>>>
>>> '%G' % 1234.567890
'1234.57'
>>>
>>> "%e" % (1111111111111111111111L)
'1.111111e+21'
整数和字符串输出:
>>> "%+d" % 4
'+4'
>>>
>>> "%+d" % -4
'-4'
>>>
>>> "we are at %d%%" % 100
'we are at 100%'
>>>
>>> 'Your host is: %s' % 'earth'
'Your host is: earth'
>>>
>>> 'Host: %s\tPort: %d' % ('mars', 80)
'Host: mars Port: 80'
>>>
>>> num = 123
>>> 'dec: %d/oct: %#o/hex: %#X' % (num, num, num)
'dec: 123/oct: 0173/hex: 0X7B'
>>>
>>> "MM/DD/YY = %02d/%02d/%d" % (2, 15, 67)
'MM/DD/YY = 02/15/67'
>>>
>>> w, p = 'Web', 'page'
>>> 'http://xxx.yyy.zzz/%s/%s.html' % (w, p)
'http://xxx.yyy.zzz/Web/page.html'
chr(), unichr(), and ord()
chr()函数用一个范围在 range(256)内的(就是 0 到 255)整数做参数,返回一个对应的字符.unichr()跟它一样,只不过返回的是 Unicode 字符
unichr()的参数范围依赖于你的 Python 是如何被编译的.如果是配置为 USC2 的 Unicode,那么它的允许范 围 就 是 range(65536) 或 者 说 0x0000-0xFFFF; 如 果 配 置 为 UCS4 , 那 么 这 个 值 应 该 是range(1114112)或0x000000-0x110000.如果提供的参数不在允许的范围内,则会报一个ValueError 的异常。
ord()函数是 chr()函数(对于 8 位的 ASCII 字符串)或 unichr()函数(对于 Unicode 对象)
的配对函数,它以一个字符(长度为 1 的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode
数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常。
| 方法 | 描述 |
|---|---|
| string.capitalize() | 把字符串的第一个字符大写 |
| string.center(width) | 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 |
| string.count(str, beg=0,end=len(string)) | 返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数 |
| string.decode(encoding=‘UTF-8’,errors=‘strict’) | 以 encoding 指定的编码格式解码 string,如果出错默认报一个ValueError 的 异 常 , 除 非 errors 指 定 的 是 ‘ignore’ 或 者’replace’ |
| string.encode(encoding=‘UTF-8’,errors=‘strict’) | 以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是’ignore’或者’replace’ |
| string.endswith(obj, beg=0,end=len(string)) | 检查字符串是否以 obj 结束,如果 beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False. |
| string.expandtabs(tabsize=8) | 把字符串 string 中的 tab 符号转为空格,默认的空格数 tabsize 是 8. |
| string.find(str, beg=0,end=len(string)) | 检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1 |
| string.index(str, beg=0,end=len(string)) | 跟 find()方法一样,只不过如果 str 不在 string 中会报一个异常. |
| string.isalnum() | 如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False |
| string.isalpha() | 如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False |
| string.isdecimal() | 如果 string 只包含十进制数字则返回 True 否则返回 False. |
| string.isdigit() | 如果 string 只包含数字则返回 True 否则返回 False. |
| string.islower() | 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False |
| string.isnumeric() | 如果 string 中只包含数字字符,则返回 True,否则返回 False |
| string.isspace() | 如果 string 中只包含空格,则返回 True,否则返回 False. |
| string.istitle() | 如果 string 是标题化的(见 title())则返回 True,否则返回 False |
| string.isupper() | 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False |
| string.join(seq) | Merges (concatenates)以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串 |
| string.ljust(width) | 返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串 |
| string.lower() | 转换 string 中所有大写字符为小写. |
| string.lstrip() | 截掉 string 左边的空格 |
| string.partition(str) | 有点像find()和split()的结合体,从str出现的第一个位置起,把字符串string分成一个3元素的元组(string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string. |
| string.replace(str1, str2,num=string.count(str1)) | 把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次. |
| string.rfind(str, beg=0,end=len(string)) | 类似于 find()函数,不过是从右边开始查找. |
| string.rindex( str, beg=0,end=len(string)) | 类似于 index(),不过是从右边开始. |
| string.rjust(width) | 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串 |
| string.rpartition(str) | 类似于 partition()函数,不过是从右边开始查找. |
| string.rstrip() | 删除 string 字符串末尾的空格. |
| string.split(str=“”, num=string.count(str)) | 以 str 为分隔符切片 string,如果 num有指定值,则仅分隔 num 个子字符串 |
| string.splitlines(num=string.count(‘\n’)) | 按照行分隔,返回一个包含各行作为元素的列表,如果 num 指定则仅切片 num 个行. |
| string.startswith(obj, beg=0,end=len(string)) | 检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查. |
| string.strip([obj]) | 在 string 上执行 lstrip()和 rstrip() |
| string.swapcase() | 翻转 string 中的大小写 |
| string.title() | 返回"标题化"的 string,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle()) |
| string.translate(str, del=“”) | 根据 str 给出的表(包含 256 个字符)转换 string 的字符,要过滤掉的字符放到 del 参数中 |
| string.upper() | 转换 string 中的小写字母为大写 |
| string.zfill(width) | 返回长度为 width 的字符串,原字符串 string 右对齐,前面填充0 |
\n 换行
\b 退格
\t 制表符
\v 纵向制表符
虽然你可以用单引号或者双引号来定义字符串,但是如果你需要包含诸如换行符这样的特殊字符时,单引号或者双引号就不是那么方便了。Python 的三引号就是为了解决这个问题的,它允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符.
>>> s = 'abc'
>>> s = s + 'def'
>>> s
'abcdef'
看起来是我们先把"abc"赋给了 s,然后在 s 的末尾添加了"def".这样看起来字符串似乎是可变的,其实事实是在"s+'def"“这个操作进行的时候,新建了一个新字符串,然后这个新的对象被赋给了 s,原来的字符串’abc’被析构掉了.我们可以用 id()函数来更明显的显示出来到底发生了什么.复习一下,id()函数返回一个对象的身份,这个概念有点类似于"内存地址”。
>> s = 'abc'
>>>
>>> id(s)
135060856
>>>
>>> s += 'def'
>>> id(s)
135057968
>>> s='abc'
>>> s[2]='a'
Traceback (most recent call last):File "", line 1, in
TypeError: 'str' object does not support item assignment
当我们要修改字符串某个值是不可行的
Unicode 通过使用一个或多个字节来表示一个字符的方法突破了 ASCII 的限制. 在这样机制下, Unicode 可以表示超过 90,000 个字符.
| 名词 | 意思 |
|---|---|
| ASCII | 美国标准信息交换码 |
| BMP | 基本多文种平面(第零平面) |
| BOM | 字节顺序标记(标识字节顺序的字符) |
| CJK/CJKV | 中文-日文-韩文(和越南语)的缩写 |
| Code point | 类似于 ASCII 值,代表 Unicode 字符的值,范围在 range(1114112)或者说0x000000 到 0x10FFFF. |
| Octet | 八位二进制数的位组 |
| UCS | 通用字符集 |
| UCS2 | UCS 的双字节编码方式(见 UTF-16) |
| UCS4 | UCS 的四字节编码方式. |
| UTF | Unicode 或者 UCS 的转换格式. |
| UTF-8 | 八位 UTF 转换格式(无符号字节序列, 长度为一到四个字节) |
| UTF-16 | 16 位 UTF 转换格式(无符号字节序列,通常是 16 位长[两个字节],见 UCS2) |
只要你遵守以下的规则,处理 Unicode 就是这么简单:
程序中出现字符串时一定要加个前缀 u.不要用 str()函数,用 unicode()代替.不要用过时的 string 模块 -- 如果传给它的是非 ASCII 字符,它会把一切搞砸。不到必须时不要在你的程序里面编解码 Unicod 字符.只在你要写入文件或数据库或者网络时,才调用 encode()函数;相应地,只在你需要把数据读回来的时候才调用 decode()函数.
**(了解)**如果你的程序里面用到了很多第三方模块,那么你很可能在各个模块统一使用 Unicode 通讯方面遇到麻烦,Unicode 还没成为一项必须的规定,在你系统里面的第三方模块(包括你的应用要面对的平台\系统)需要用相同的 Unicode 编码,否则,可能你就不能正确的读写数据.作为一个例子,假设你正在构建一个用数据库来读写 Unicode 数据的 Web 应用.为了支持Unicode,你必须确保以下方面对 Unicode 的支持:
数据库服务器(MySQL,PostgreSQL,SQL Server,等等)
数据库适配器(MySQLdb 等等)
Web 开发框架(mod_python,cgi,Zope,Plane,Django 等等)
数据库方面最容易对付,你只要确保每张表都用 UTF-8 编码就可以了。
数据库适配器可能有点麻烦,有些适配器支持 Unicode 有些不支持,比如说 MySQLdb,它并
不是默认就支持 Unicode 模式,你必须在 connect()方法里面用一个特殊的关键字 use_unicode
来确保你得到的查询结果是 Unicode 字符串.
mod_python 里 面 开 启 对 Unicode 的 支 持 相 当 简 单 , 只 要 在 request 对 象 里 面 把
text-encoding 一项设成"utf-8"就行了,剩下的 mod_python 都会替你完成,Zope 等其他复杂
的系统可能需要更多的工作来支持 Unicode.
内建的 unicode()函数
Unicode 的工厂方法,同 Unicode 字符串操作符(u / U)的工作方式很类似,它接受一个string 做参数,返回一个 Unicode 字符串.
内建的 decode()/encode()方法
decode()和 encode()内建函数接受一个字符串做参数返回该字符串对应的解码后/编码后的字符串.decode()和 encode()都可以应用于常规字符串和 Unicode 字符串.decode()方法是在Python2.2 以后加入的.
Unicode 类型
Unicode 字符串对象是 basestring 的子类、用 Unicode()工厂方法或直接在字符串前面加一个 u 或者 U 来创建实例.支持 Unicode 原始字符串,只要在你的字符串前面加一个 ur 或者 UR就可以了.
Unicode 序数
标准内建函数 ord()工作方式相同,最近已经升级到可以支持 Unicode 对象了。内建的unichr()函数返回一个对应的 Unicode 字符(需要一个 32 位的值);否则就产生一个 ValueError异常.
强制类型转换
混合类型字符串操作需要把普通字符串转换成 Unicode 对象.
异常
UnicodeError 异常是在 exceptions 模块中定义的,ValueError 的子类.所有关于 Unicode编解码的异常都要继承自 UnicodeError.详见 encode()函数.
常用 Unicode 编辑码
| 编码 | 描述 |
|---|---|
| utf-8 | 变量长度为 8 的编码(默认编码) |
| utf-16 | 变量长度为 16 的编码(大/小端) |
| utf-16-le | 小端 UTF-16 编码 |
| utf-16-be | 大端 UTF-16 编码 |
| ascii | 7-bit 7 位 ASCII 码表 |
| iso-8859-1 | ISO 8859-1 (Latin-1) 码表 |
| unicode-escape | (定义见 Python Unicode 构造函数) |
| raw-unicode-escape | (定义见 Python Unicode 构造函数) |
| native | Python 用的内部格式 |
u"%s %s" % (u"abc", “abc”) u"abc abc"
| 模块 | 描述 |
|---|---|
| string | 字符串操作相关函数和工具,比如 Template 类. |
| re | 正则表达式:强大的字符串模式匹配模块 |
| struct | 字符串和二进制之间的转换 |
| c/StringIO | 字符串缓冲对象,操作方法类似于 file 对象. |
| base64 | Base 16,32,64 数据编解码 |
| codecs | 解码器注册和基类 |
| crypt | 进行单方面加密 |
| difflib | 找出序列间的不同 |
| hashlib | 多种不同安全哈希算法和信息摘要算法的 API |
| hma | HMAC 信息鉴权算法的 Python 实现 |
| md5 | RSA 的 MD5 信息摘要鉴权 |
| rotor | 提供多平台的加解密服务 |
| sha | NIAT 的安全哈希算法 SHA |
| stringprep | 提供用于 IP 协议的 Unicode 字符串 |
| textwrap | 文本打包和填充 |
| unicodedata | Unicode 数据库 |
**正则表达式(RE)**提供了高级的字符串模式匹配方案.通过描述这些模式的语法,你可以像使用“过滤器”一样高效地查找传进来的文本。这些过滤器允许你基于自定义的模式字符串抽取匹配模式、执行查找-替换或分割字符串.Python1.5 中加入的 re 模块代替了早期的 regex 和 regsub 模块,全面采用了 Perl 正则表达式语法,使得 Python 在对正则表达式的支持方面前进了一大步. Python1.6 里面重写了正则表达式引擎(SRE),增加了对 Unicode 字符串的支持并对性能进行了重大的升级.SRE 引擎取代了
原有正则表达式的模块下的 PCRE 引擎.该模块中包含的关键函数有:compile() - 将一个 RE 表达式编译成一个可重用的 RE 对象;match() - 试图从字符串的开始匹配一个模式;search() - 找出字符串中所有匹配的项;sub() - 进行查找替换操作。其中的一些函数返回匹配到的对象,你可以通过组匹配来访问(如果找到的话)。15 章的整章内容都是讲述正则表达式。
字符串是唯一的字面上的字符序列类型.不过,字符本身并不是一种类型,所以,字符串是字符存储操作的最基本单位.字符应该视为长度为 1 的字符串.