您所在的位置:小祥子 » 编程 » Python » 正文

06 序列:字符串、列表和元组

时间:2015-08-15 编辑:《Python 核心编程》 来源:CnBlogs
?? 序列简介 ?? 字符串 ?? 列表 ?? 元组 6.1 序列顺序访问     序列类型有着相同的访问模式:它的每一个元素可以通过指定一个偏移量的方式得到。     而多个元素可以通过切片操作的方式一次得到。     下标偏移量是从0 开始到总元素数-1 结束。 标准类型操作符     标准类型操作符一般都能适用于所有的序列类型。 序列类型操作符     成员关系操作符 (in, not in)     连接操作符( + )     重复操作符 ( * )     切片操作符 ( [], [:], [::] )  正负索引的区别在于正索引以序列的开始为起点,负索引以序列的结束为起点.     表6.1 序列类型操作符     序列操作符            作用     seq[ind]               获得下标为ind 的元素     seq[ind1:ind2]     获得下标从ind1 到ind2 间的元素集合(不包含索引为ind2的元素)     seq * expr            序列重复expr 次     seq1 + seq2         连接序列seq1 和seq2     obj in seq            判断obj 元素是否包含在seq 中     obj not in seq     判断obj 元素是否不包含在seq 中     成员关系操作符 (in, not in)         成员关系操作符使用来判断一个元素是否属于一个序列的。             对字符串类型来说,就是 判断一个字符是否属于这个字符串。             对和元组类型来说,就代表了一个对象是否属于该对象序列。     连接操作符( + )         连接操作符允许我们把一个序列和另一个相同类型的序列做连接。         连接操作符不是最快或者说最有效的。         对于符串             连接操作符不如把所有的子字符串放到一个列表或可迭代对象中,然后调用一个join方法来把所有的内容连接在一起节约内存;                             对列表             我们推荐读者用列表类型的extend()方法来把两个或者多个列表对象合并.     重复操作符 ( * )         当你需要需要一个序列的多份拷贝时,重复操作符像连接操作符一样,该操作符返回一个新的包含多份原对象拷贝的对象。     切片操作符 ( [], [:], [::] )         简单地讲,所谓序列类型就是包含一些顺序排列的对象的一个结构.             你可以简单的用方括号 加一个下标的方式访问它的每一个元素,             或者通过在方括号中用冒号把开始下标和结束下标分开的方式来访问一组连续的元素.             sequence[index]                 sequence 是序列的名字,index 是想要访问的元素对应的偏移量.                 偏移量的范围是 -len(sequence) < 0 <= inde <= len(sequece)-1                  正负索引的区别在于正索引以序列的开始为起点,负索引以序列的结束为起点.             sequence[starting_index:ending_index]                 通过这种方式我们可以得到从起始索引到结束索引(不包括结束索引对应的元素)之间的 一"片"元素.                 起始索引和结束索引都是可选的.                     如果没有提供或者用None 作为索引值,切片操作会从序列的最开始处开始,或者直到序列的最末尾结束.             sequence[starting_index:ending_index:step_index]                 用步长索引来进行扩展的切片操作 ,它多出来的第三个索引值被用做步长参数。 内建函数(BIFs)     可迭代对象         迭代这个概念就是从序列,迭代器,或者其他支持迭代操作的对象中泛化得来的,因此序列本身就内含了迭代的概念。         Python 的for 循环可以遍历所有的可迭代类型,在(非纯序列对象上)执行for 循环时就像在一个纯序列对象上执行一样。         Python 的很多原来只支持序列作为参数的内建函数现在也开始支持迭代器或者或类迭代器了.     类型转换         内建函数list(),str()和tuple()被用做在各种序列类型之间转换。         你可以把它们理解成 其他语言里面的类型转换,但是并没有进行任何的转换。         这些转换实际上是工厂函数,将对象作为参数,并将其内容(浅)拷贝到新生成的对象中.             所谓浅拷贝就是只拷贝了对对象的索引,而不是重新建立了一个对象。             如果你想完全的拷贝一个对象(包括递归,如果你的对象是一个包含在容器中的容器),你需要用到深拷贝.         表 6.2 序列类型转换工厂函数         函数                      含义         list(iter)                把可迭代对象转换为列表         str(obj)                 把obj 对象转换成字符串(对象的字符串表示法)         unicode(obj)       把对象转换成Unicode 字符串(使用默认编码)         basestring()         抽象工厂函数,其作用仅仅是为str 和unicode 函数提供父类,所以不能被实例化,也不能被调用         tuple(iter)            把一个可迭代对象转换成一个元组对象         str()              str()函数在需要把一个对象的可打印信息输出时特别有用,不仅仅是对序列类型,对其他类型的对象同样如此.         Unicode()              Unicode()是str()函数的unicode 版本,它跟str()函数基本一样.         list() 和tuple()             list() 和tuple()函数在列表类型和元组类型的互换时非常有用.     Operational                 6.2 字符串     Python 里面单引号和双引号的作用是相同的.     Python 用"原始字符串"操作符来创建直接量字符串.     字符串是不可变类型.     字符串是由独立的字符组成的,并且这些字符可以通过切片操作顺序地访问. 字符串的创建和赋值     创建一个字符串就像使用一个标量一样简单,当然你也可以把str()作为工厂方法来创建一个字符串并把它赋值给一个变量. 如何访问字符串的值(字符和子串)     Python 里面没有字符这个类型,而是用长度为1 的字符串来表示这个概念,当然,这其实也是一个子串。     用方括号加一个或者多于一个索引的方式来获得子串。 如何改变字符串     跟数字类型一样,字符串类型也是不可变的,所以你要改变一个字符串就必须通过创建一个新串的方式来实现. 如何删除字符和字符串     字符串是不可变的,所以你不能仅仅删除一个字符串里的某个字符.         你能做的是清空一个空字符串,         或者是把剔除了不需要的部分后的字符串组合起来形成一个新串. 6.3 字符串和操作符 标准类型操作符         >>> str1 = 'abc'          >>> str2 = 'lmn'          >>> str3 = 'xyz'          >>> str1 < str2          True          >>> str2 != str3          True          >>> str1 < str3 and str2 == 'xyz'          False 序列操作符     切片( [ ] 和 [ : ] )         ?? 正向索引    final_index = len(aString) - 1         ?? 反向索引    final_index = -len(aString)         ?? 默认索引         字符串'abcd'                            正向索引时,索引值开始于0,结束于总长度减1(因为我们是从0 开始索引的).                 用一个参数来调用切片操作符结果是一个单一字符.                 用一个数值范围(用':')作为参数调用切片操作的参数会返回一串连续地字符.             反向索引时,索引值是从-1 开始,向字符串的开始方向计数,到字符串长度的负数为索引的结束。             如果开始索引或者结束索引没有被指定,则分别以字符串的第一个和最后一个索引值为默认值。     成员操作符(in ,not in)         成员操作符用于判断一个字符或者一个子串(中的字符)是否出现在另一个字符串中     连接符( + )         运行时刻字符串连接             Python 必须为每一个参加连接操作的字符串分配新的内存,包括新产生的字符串。             推荐使用字符串格式化操作符(%),或者把所有的字符串放到一个列表中去,然后用一个join()方法来把它们连接在一起。             >>> '%s %s' % ('Spanish', 'Inquisition')              'Spanish Inquisition'              >>>              >>> s = ' '.join(('Spanish', 'Inquisition', 'Made Easy'))              >>> s              'Spanish Inquisition Made Easy'              >>>              >>> # no need to import string to use string.upper():              >>> ('%s%s' % (s[:3], s[20])).upper()              'SPAM'         编译时字符串连接             Python 的语法允许你在源码中把几个 字符串连在一起写,以此来构建新字符串:             >>> foo = "Hello" 'world!'              >>> foo              'Helloworld!'                 你可以把长的字符串分成几部分来写,而不用加反斜杠                 你可以在一行里面混用两种分号                 你可以把注释也加进来         普通字符串转化为Unicode 字符串             如果把一个普通字符串和一个Unicode 字符串做连接处理,Python 会在连接操作前先把普通字符串转化为Unicode 字符串     重复操作符( * )         重复操作符创建一个包含了原有字符串的多个拷贝的新串:          >>> 'Ni!' * 3          'Ni!Ni!Ni!' 6.4 只适用于字符串的操作符 格式化操作符( % )     Python 风格的字符串格式化操作符。     只适用于字符串类型。     类似于C 语言里面的printf()函数的字符串格式化,甚至所用的符号都一样,都用百分号(%),并且支持所有printf()式的格式化操作。              格式字符串既可以跟print 语句一起用来向终端用户输出数据,         又可以用来合并字符串形 成新字符串,
        而且还可以直接显示到GUI(Graphical User Interface)界面上去。     Python 支持两种格式的输入参数。         元组             C printf()风格的转换参数集             >>> w, p = 'Web', 'page'              >>> 'http://xxx.yyy.zzz/%s/%s.html' % (w, p)              'http://xxx.yyy.zzz/Web/page.html'         字典             key 是作为格式字符串出现,相对应的value 值作为参数在进行转化时提 供给格式字符串.             >>> 'There are %(howmany)d %(lang)s Quotation Symbols' % {'lang': 'Python', 'howmany': 3}              'There are 3 Python Quotation Symbols'                        字符串模板     新式的字符串Template 对象有两个方法,substitute()和safe_substitute().         substitute() 严谨,在key 缺少的情况下它会报一个KeyError 的异常出来.         safe_substitute()在缺少key 时,直接原封不动的把字符串显示出来.         >>> from string import Template          >>> s = Template('There are ${howmany} ${lang} Quotatin Sysmbols')          >>> print s.substitute(lang='Python', howmany=3)          There are 3 Python Quotatin Sysmbols          >>> 原始字符串操作符( r/R )     原始字符串的目的是为了对付那些在字符串中出现的特殊字符。         在原始字符串里,所有的字符都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符。     原始字符串符号(引号前面的字母"r"),这个'r'可以是小写也可以是大写,唯一的要求是必须紧靠在第一个引号前.         >>> print '\n'                            >>> print r'\n'          \n          >>>         Note: Raw strings are not 100% raw, there is still some rudimentary backslash-processing. Unicode 字符串操作符( u/U )     Unocide 字符串操作符,大写的(U)和小写的(u)是在Python1.6 中 和 Unicode 字符串一 起被引入的.      Unocide 用来把标准字符串或者是包含Unicode 字符的字符串转换成完全地Unicode 字符串对象。     Unicode 操作符必须出现在原始字符串操作符前面. 6.5 内建函数 标准类型函数     cmp()         同比较操作符一样,内建的cmp()函数也根据字符串的ASCII 码值进行比较.         >>> str1 = 'abc'          >>> str2 = 'lmn'          >>> str3 = 'xyz'          >>> cmp(str1, str2)          -1         >>> cmp(str3, str1)          1         >>> cmp(str2, 'lmn')          0 序列类型函数     len()         内建函数len()返回字符串的字符数.     max() and min()         对于string 类型,返回最大或者最小的字符,(按照ASCII 码值排列).     enumerate()         >>> s = 'foobar'          >>> for i, t in enumerate(s):          ... print i, t          ...          0 f          1 o          2 o          3 b          4 a          5 r     zip()         >>> s, t = 'foa', 'obr'          >>> zip(s, t)          [('f', 'o'), ('o', 'b'), ('a', 'r')]     字符串类型函数     raw_input()input()         内建的raw_input()函数使用给定字符串提示用户输入并将这个输入返回.         Python 里面没有C 风格的结束字符NUL,你输入多少个字符,len()函数的返回值就是多少.         >>> user_input = raw_input('Enter your name: ')          Enter your name: John Doe          >>> user_input          'John Doe'          >>> len(user_input)          8          >>>     str() and unicode()          str()和unicode()函数都是工厂函数,就是说产生所对应的类型的对象.         它们接受一个任 意类型的对象,然后创建该对象的可打印的或者Unicode 的字符串表示.          它们和basestring 都可以作为参数传给isinstance()函数来判断一个对象的类型.          >>> isinstance(u'\0xAB', str)          False          >>> not isinstance('foo', unicode)          True          >>> isinstance(u'', basestring)          True          >>> not isinstance('foo', basestring)          False     chr(), unichr(), and ord()         chr()             chr()函数用一个范围在range(256)内的(就是0 到255)整数做参数,返回一个对应的字 符.         unichr()              unichr()跟 chr() 一样,只不过返回的是Unicode 字符.             从Python2.0 才加入的unichr()的参数范围依赖于你的Python 是如何被编译的.                 如果是配置为USC2 的Unicode,那么它的允许范围就是range(65536) 或者说0x0000-0xFFFF;                  如果配置为UCS4 , 那么这个值应该是range(1114112)或者0x000000-0x110000.                 如果提供的参数不在允许的范围内,则会报一个ValueError 的异常。          ord()                     ord()函数是chr()函数(对于8 位的ASCII 字符串)或unichr()函数(对于Unicode 对象) 的配对函数.             ord()函数以一个字符(长度为1 的字符串)作为参数,返回对应的ASCII 数值,或者Unicode数值.             如果所给的Unicode 字符超出了你的Python 定义范围,则会引发一个TypeError 的异常。 6.6 字符串内建函数     string.capitalize()    把字符串的第一个字符大写     string.center(width)返回一个原字符串居中,并使用空格填充至长度width 的新字符串 6.7 字符串的独特特性 特殊字符串和控制字符     像其他高级语言和脚本语言一样,一个反斜线加一个单一字符可以表示一个特殊字符,         通常是一个不可打印的字符,这就是我们上面讨论的特殊字符,         如果这些特殊字符是包含在一个原始字符串中的,那么它就失去了转义的功能.

        特殊字符,包括反斜杠转义的那些都可以像普通字符一样存储到Python 的字符串中.

     NUL         跟C 字符串的另一个不同之处是Python 的字符串并不是以NUL(\000)作为结束符的.         NUL 跟 其他的反斜杠转义字符没什么两样.     控制字符的一个作用是用做字符串里面的定界符.             三引号         Python 的三引号(一对连续的单引号或者双引号)允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符. 字符串不变性         字符串是一种不可变数据类型,它的值是不能被改变或修改的。 [构造与析构] 6.8 Unicode     Unicode 字符串支持,是用来在多种双字节字符的格式、编码进行转换的,其中包括一些对这类字符串的操作管理功能。 Unicode 术语              什么是Unicode?     ASCII 码         ASCII 码的每个英文字符都是以7位二进制数的方式存贮在计算机内,其可打印字符范围是32 到126.             当用户在文件中键入一个大写字符A 时,计算机会把A 的ASCII 码值65写入磁盘,             当计算机读取该文件时,它会首先把65 转化成字符A 然后显示到屏幕上.          ASCII 编码的文件小巧易读。             一个程序只需简单地把文件的每个字节读出来,把对应的数 值转换成字符显示出来就可以了.             但是ASCII 字符只能表示95 个可打印字符.             后来的软件厂商把ASCII 码扩展到了8 位,这样一来它就可以多标识128 个字符,             可是223 个字符对需要成千上万的字符的非欧洲语系的语言来说仍然太少 你是怎么用Unicode 的?     为了让Unicode 和ASCII 码值的字符串看起来尽可能的相像,Python 的字符串从原来的简 单数据类型改成了真正的对象.     ASCII 字符串成了StringType,而Unicode 字符串成了UnicodeType 类型.     string 模块         string 模 块已经停止了更新,只保留了ASCII 码的支持,         string 模块已经不推荐使用,在任何需要跟Unicode 兼容的代码里都不要再用该模块,Python 保留该模块仅仅是为了向后兼容。     Unicode 字符串      Python 把硬编码的字符串叫做字面上的字符串,默认所有字面上的字符串都用ASCII 编码,     可以通过在字符串前面加一个'u'前缀的方式声明Unicode 字符串, 这个'u'前缀告诉Python 后面的字符串要编码成Unicode字符串 .         >>> "Hello World" # ASCII string          >>> u"Hello World" # Unicode string     内建的str()函数和chr()函数          内建的str()函数和chr()函数并没有升级成可以处理Unicode.         它们只能处理常规的 ASCII 编码字符串.         str()函数             如果一个Unicode 字符串被作作为参数传给了str()函数,它会首先被转换成ASCII 字符串然后在交给str()函数.             如果该Unicode 字符串中包含任何不被ASCII 字符串支持的字符,会导致str()函数报异常.         chr()函数             同样地,chr()函数只能以0 到255 作为参数工作.             如果你传给它一个超出此范围的值(比如说一个Unicode 字符),它会报异常.      内建的unicode()函数和unichr()函数         新的内建函数unicode()和unichr()可以看成Unicode 版本的str()和chr().         Unicode() 函数可以把任何Python 的数据类型转换成一个Unicode 字符串,         如果是对象,并且该对象定义了__unicode__()方法,它还可以把该对象转换成相应的Unicode 字符串. Codecs 是什么?     codec         codec 是COder/DECoder 的首字母组合.         它定义了文本跟二进制值的转换方式,         ascii 用一个字节把字符转换成数字的方式不同.         unicode 用的是多字节.         unicode 支持多种不同的编码方式.          codec 支持的四种耳熟能详的编码方式是 :ASCII,ISO8859-1/Latin-1,UTF-8 和UTF-16.     UTF-8         ASCII 字符的UTF-8 编码跟ASCII 编 码完全相同.         UTF-8 编码可以用1 个到4 个字节来表示其他语言的字符.     UTF-16         UTF-16 把所有的字符都是用单 独的一个16 位字,两个字节来存储.         UTF-16 编码文件都需要一个BOM(Byte Order Mark),或者你显式地定义UTF-16-LE(小端)或 者UTF-16-BE(大端)字节序.         UTF-16 也是一种变长编码.         UTF-16 不向后兼容 ASCII. 编码解码     Unicode 支持多种编码格式,这为程序员带来了额外的负担.     每次我们写一个Unicode 字符串到磁盘上我们都要用指定的编码器给他"编码"一下.     相应地,当我们从这个文件读取数据时,我们必须"解码"该文件,使之成为相应的Unicode 字符 串对象. 把Unicode 应用到实际应用中     处理Unicode 字符串的规则         ?? 程序中出现字符串时一定要加个前缀 u.         ?? 不要用 str()函数,用unicode()代替.         ?? 不要用过时的 string 模块 -- 如果传给它的是非ASCII 字符,它会把一切搞砸。         ?? 不到必须时不要在你的程序里面编解码 Unicod 字符.             只在你要写入文件或数据库或者 网络时,才调用encode()函数;相应地,只在你需要把数据读回来的时候才调用decode()函数. 从现实中得来的教训     失误 #1: 你必须在一个极有限的时间内写出一个大型的应用,而且需要其他语言的支持,         但是产品经理并没有明确定义这一点。你并没有考虑Unicode 的兼容,直到项目快要结束... ,          这时候再添加Unicode 的支持几乎不太可能,不是吗?      结果 #1: 没能预测到最终用户对其他语言界面的需求,在集成他们用的面向其他语种的应         用时又没有使用Unicode 支持.更新整个系统既让让人觉得枯燥和更是浪费时间。      失误 #2:在源码中到处使用string 模块或者str()和chr()函数.      结果 #2:通过全局的查找替换把str()和chr()替换成unicode()和unichr(),但是这样一         来很可能就不能再用pickle 模块,要用只能把所有要pickle 处理的数据存成二进制形式,这         样一来就必须修改数据库的结构,而修改数据库结构就意味着全部推倒重来.      失误 #3: 不能确定所有的辅助系统都完全地支持Unicode.      结果 #3: 不得不去为那些系统打补丁,而其中有些系统可能你根本就没有源码.修复对         Unicode 支持的bug 可能会降低代码的可靠性,而且非常有可能引入新的bug.      总结: 使应用程序完全支持Unicode,兼容其他的语言本身就是一个工程.      它需要详细的考虑、计划.所有涉及到的软件、系统都需要检查,包括Python 的标准库和其     他将要用到的第三方扩展模块.你甚至有可能需要组建一个经验丰富的团队来专门负责国际化(I18N)问题. Python 的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()函数.     标准编码                RE 引擎对Unicode 的支持         正则表达式引擎需要Unicode 支持.详见 re 模块.     字符串格式化操作符         Python 的格式化字符串的操作符 %s 把Python 字符串中的Unicode 对象执行了 str(u)操作, 输出的应该是u.encode(默认编码).         如果格式化字符串是Unicode 对象, 所 有的参数都将首先强制转换成Unicode 然后根据对应的格式串一起进行格式转换.             数字首先被转换成普通字符串, 然后在转换成Unicode.             Python 字符串通过默认编码格式转化成Unicode.             Unicode 对象不变,所有其他格式字符串都需要像上面这样转化,下面是例子:                 u"%s %s" % (u"abc", "abc")   u"abc abc" 6.9 相关模块 Python 标准库里面与字符串有关的主要模块.              6.10 字符串关键点总结 一些引号分隔的字符     在Python 中最常用两个引号是单引号(')和双引号("),字符串 的内容是这些单引号(')或者双引号(")之间的字符,不包括引号本身.     当你的字符串中包含双引号时,如果 用单引号创建字符串,那么字符串中的双引号就不需要转义。反之亦然. 不可分字符类型     字符串是唯一的字面上的字符序列类型.     不过,字符本身并不是一种类型,所以,字符串是字 符存储操作的最基本单位.     字符应该视为长度为1 的字符串. 字符串格式化操作符 ( % )     字符串格式化操作符提供类似于printf()那样的功能.     字符串格式化操作符提供了一种基于多种输入类型的创建自定义字符串的灵 活方式.     字符串格式化操作符提供了类似于C/C++世界里的格式化操作的接口. 三引号     在三引号字符串中可以包含诸如换行回车或者tab 键 这样的特殊字符.     三引号字符串是用两边各三个单引号(''')或者两边各三个双引号(""")来定义的. 原始字符串(r/R)     原始字符串对每个特殊字符串都使用它的原意.     原始字符串非常适用于那些需要字符串原意的场合,比如定义一个正则表达 式. Python 字符串不是通过NUL 或者'\0'来结束的     C 编程的一个主要问题是你访问了一个字符串后面的本不属于你的空间,这种情况发生在你 没有在字符串末尾添加终结符,NUL 或者'\0'(ASCII 值为0)的时候.     Python 不仅为你自动管理内 存,而且也把C 的这个负担或者说是小麻烦去掉了.     Python 中的字符串不是以NUL 结束的,所以你不需要为是否已经添加终结符担心.字符串中只包含你所定义的东西,没有别的. 6.11 列表 如何创建列表类型数据并给它赋值     方括号([])         列表是由方括号([])来定义的     工厂方法(list())         列表也可以用工厂方法来创建     如何访问列表中的值     切片操作符 如何更新列表     通过在等号的左边指定一个索引或者索引范围的方式来更新一个或几个元素     通过用append()方法来追加元素到列表中去. 如何删除列表中的元素或者列表(本身)     要删除列表中的元素,如果你确切的知道要删除元素的索引可以用del 语句,否则可以用remove()方法.     你还可以通过pop()方法来删除并从列表中返回一个特定对象.     一般来说,程序员不需要去删除一个列表对象。列表对象出了作用域(比如程序结束,函数调用完成等等)后它会自动被析构,但是如果你想明确的删除一整个列表,你可以用del 语句:del aList 6.12 列表操作符 标准类型操作符     比较列表时也是用的内建的cmp()函数,基本的比较逻辑 是这样的:两个列表的元素分别比较,直到有一方的元素胜出。 序列类型操作符     切片([] 和[:])         列表的切片操作跟字符串的切片操作很像,不过列表的切片操作返回的是一个对象或者是几个对象的集合,而不是像字符串那样,返回一个字符或者一个子串.         列表的切片操作也遵从正负索引规则,也有开始索引值,结束索引值,如果这两个值为空,默 认也会分别指到序列的开始和结束位置.     成员关系操作( in ,not in)         列表中(同样适用于元组),我们可以检查一个对象是否是一个列表(或者元组)的成员.     连接接操作符( + )         extend()方法                     可以用extend()方法来代替连接操作符把一个列表的内容添加到另一个中去.             使用extend()方法比连接操作的一个优点是它实际上是把新列表添加到了原有的列表里面,而不是像连接操作那样新建一个列表。             list.extend()方法也被用来做复合赋值运算,也就是Python2.0 中添加的替换连接操作(+=).             连接操作符并不能实现向列表中添加新元素的操作.      内建函数append()         把一个对象作为一个新元素添 加到列表中。         >>> num_list.append('new item') 重复操作符( * )     重复操作符可能更多的应用在字符串类型中,不过,列表和元组跟字符串同属序列类型,所 以需要的时候也可以使用这一操作.         >>> num_list * 2          [43, -1.23, -2, 619000.0, 43, -1.23, -2, 619000.0]          >>>     Python2.0 起,也开始支持复合赋值运算:         >>> hr = '-'          >>> hr *= 30          >>> hr          '------------------------------' 列表类型操作符和列表解析     列表类型的操作符          Python 中没有专门用于列表类型的操作符.         列表可以使用大部分的对象和序列类型的操作符.         列表类型有属于自己的方法.列表才有的构建--列表解析.这种方法是结合了列表的方括弧和for循环,在逻辑上描述要创建的列表的内容.             >>> [ i * 2 for i in [8, -2, 5] ]              [16, -4, 10]              >>> [ i for i in range(8) if i % 2 == 0 ]              [0, 2, 4, 6] 6.13 列表内建函数 标准类型函数     cmp()         1. 对两个列表的元素进行比较.         2. 如果比较的元素是同类型的,则比较其值,返回结果.         3. 如果两个元素不是同一种类型,则检查它们是否是数字.             a. 如果是数字,执行必要的数字强制类型转换,然后比较.     b. 如果有一方的元素是数字,则另一方的元素"大"(数字是"最小的")     c. 否则,通过类型名字的字母顺序进行比较.         4. 如果有一个列表首先到达末尾,则另一个长一点的列表"大".         5. 如果我们用尽了两个列表的元素而且所有元素都是相等的,那么结果就是个平局,就是说返回一个0. 序列类型函数     len()         返回列表或者元组的元素个数,容器里面的每个对象被作为一个项来处理.     max() and min()         max()和min()函数在字符串操作里面用处不大,因为它们能对字符串做的只能是找出字符 中"最大"和"最小"的字符(按词典序),而对列表和元组来说,它们被定义了更多的用处.            容器的混合对象的结构越复杂返回的结构准确性就越差.              sorted() and reversed()         注意字 符串排序使用的是字典序, 而不是字母序(字母'T'的ASCII 码值要比字母'a'的还要靠前)     enumerate() and zip()         >>> albums = ['talbes', 'robot', 'pyramid']          >>> for i, album in enumerate(albums):          ... print i, album          ...          0 talbes          1 robot          2 pyramid          >>> fn = ['ian', 'stuart', 'david']          >>> ln = ['bairnson', 'elliott', 'paton']          >>> for i, j in zip(fn,ln):          ... print ('%s %s' % (i,j)).title()          ...          Ian Bairnson          Stuart Elliott          David Paton          >>>     sum()         >>> a = [6, 4, 5]          >>> reduce(operator.add, a)          15          >>> sum(a)          15          >>> sum(a, 5)          20          >>> a = [6., 4., 5.]          >>> sum(a)          15.0     list() and tuple()         list()函数和tuple()函数接受可迭代对象(比如另一个序列)作为参数,并通过浅拷贝数据 来创建一个新的列表或者元组.             >>> aTuple = (1,2,3)              >>> aList = list(aTuple)              >>> aTuple is aList              False              >>> aList[0] = 10              >>> aList              [10, 2, 3]              >>> aTuple              (1, 2, 3)              >>> 列表类型内建函数     如果你不考虑range()函数的话,Python 中没有特定用于列表的内建函数.     range()函数接 受一个数值作为输入,输出一个符合标准的列表     列表类型对象可以使用大多数的对象和序列的内建函数,并且,列表对象有属于它们自己的方法. 6.14 列表类型的内建函数               index()         用index()来检查一个元素是否存在于一个list 中并不是个好主意.         应该先用in 成员关系操作符(或者是not in)检查一下,然后在用index()找到这个元素的位置。             >>> aList = ['a','e','i','o']              >>> aList.index('A')              Traceback (most recent call last):                File "<stdin>", line 1, in <module>              ValueError: 'A' is not in list              >>> 'A' in aList              False     核心笔记: 那些可以改变对象值的可变对象的方法是没有返回值的!          不可变对象的方法是不能改变它们的值的,所以它们必须 返回一个新的对象.

6.15 列表的特殊特性

    列表有容器和可变的特性,这使得它非常灵活,用它来构建其他的数据结构不是件难事. 用列表构建其他数据结构     堆栈         堆栈是一个后进先出(LIFO)的数据结构,其工作方式就像自助餐厅里面用于放盘子的弹簧支架.         把盘子想像成对象,第一个离开堆栈的是你最后放上的那个.         在栈上"push"元素是个常用术语,意思是把一个对象添加到堆栈中.         反之,要删除一个元素,你可以把它"pop"出堆栈.     队列         队列是一种先进先出(FIFO)的数据类型,它的工作原理类似于超市中排队交钱或者银行里面的排队,队列里的第一个人首先接受服务(满心想第一个出去).         新的元素通过"入队"的方式添加进队列的末尾,"出队"就是从队列的头部删除. 6.16 元组     元组是跟列表非常相近的另一种容器类型.     元组和列表看起来不同的一点是元组用的是圆括号而列表用的是方括号.     功能上,元组和列表相比有一个很重要的区别,元组是一种不可变类型. 如何创建一个元组并给它赋值     圆括号([])         元组是由圆括号(())来定义的         创建一个元组并给他赋值实际上跟创建一个列表并给它赋值完全一样,除了一点,只有一个元素的元组需要在元组分割符里面加一个逗号(,)用以防止跟普通的分组操作符混淆.     工厂方法tuple())         元组也可以用工厂方法来创建     如何访问元组中的值     切片操作符         元组的切片操作跟列表一样,用方括号作为切片操符([]),里面写上索引值或者索引范围. 如何更新元组     跟数字和字符串一样,元组也是不可变类型,就是说你不能更新或者改变元组的元素. 如何移除一个元组的元素以及元组本身     删除一个单独的元组元素是不可能的,当然,把不需要的元素丢弃后, 重新组成一个元组是 没有问题的.      del aTuple         要显示地删除一整个元组,只要用del 语句减少对象引用计数.         当这个引用计数达到0 的时 候,该对象就会被析构.         记住,大多数时候,我们不需要显式的用del 删除一个对象,一出它的作用域它就会被析构,Python 编程里面用到显式删除元组的情况非常之少.  6.17 元组操作符和内建函数 标准类型操作符,序列类型操作符和内建函数.     创建,重复,连接操作         >>> t = tuple('foo')          >>> t          ('f', 'o', 'o')          >>> t * 2          ('f', 'o', 'o', 'f', 'o', 'o')          >>> t + tuple('bar')          ('f', 'o', 'o', 'b', 'a', 'r')          >>>     成员关系操作,切片操作         >>> 'f' in t          True          >>> t[0:2]          ('f', 'o')          >>>     内建函数         >>> str(t)          "('f', 'o', 'o')"          >>> max(t)          'o'          >>> min(t)          'f'          >>> list(t)          ['f', 'o', 'o']          >>>     操作符         >>> t==t          True          >>> b = tuple('bar')          >>> b > t          False          >>> t > b          True          >>> b == t          False          >>> 元组类型操作符和内建函数,内建方法     像列表一样 元组也没有它自己专用的运算符和内建函数. 6.18 元组的特殊特性. 不可变性给元组带来了什么影响?     三个标准不可变类型--数字,字符串和元组字符串.     一个数 据类型是不可变的,简单来讲,就意味着一旦一个对象被定义了,它的值就不能再被更新,除非重新创建一个新的对象.     不可变并不是坏事,比如我们把数据传给一个不了解的API 时,可以确保我们的数据不会被修改。     同样地,如果我们操作从一个函数返回的元组,可以通过内建list()函数把它转换成一个列表. 元组也不是那么“不可变”     虽然元组对象本身是不可变的,但这并不意味着元组包含的可变对象也不可变了。         >>> t = ([0],1,2)          >>> t[0][0] = ['Hello', 'Kitty']          >>> t          ([['Hello', 'Kitty']], 1, 2)          >>> 默认集合类型     所有的多对象的,逗号分隔的,没有明确用符号定义的,比如说像用方括号表示列表和用圆括号表示元组一样,等等这些集合默认的类型都是元组.         >>> x, y = 1, 2          >>> x, y          (1, 2)     所有函数返回的多对象(不包括有符号封装的)都是元组类型。注意,有符号封装的多对 象集合其实是返回的一个单一的容器对象.         >>> def foo1():          ... return 1,2,3          ...          >>> def foo2():          ... return [1,2,3]          ...          >>> def foo3():          ... return (1,2,3)          ...          >>> foo1()          (1, 2, 3)          >>> foo2()          [1, 2, 3]          >>> foo3()          (1, 2, 3)          >>>     为了避免令人讨厌的副作用,建议总是显式的用圆括号表达式表示元组或者创建一个元组.         >>> 4, 2 < 3, 5 # int, comparison, int          (4, True, 5)          >>> (4, 2) < (3, 5) # tuple comparison          False 单元素元组     圆括号被重载了,它也被用作分组操作符。由圆括号包裹的一个单一元素首先被作为分组操作,而不是作为元组的分界符。     一个变通的方法是在第一个元素后面添一个逗号(,)来表明这是一个元组而不是在做分组操作.         >>> ('xyz')          'xyz'          >>> ('xyz',)          ('xyz',)          >>> 字典的关键字     不可变对象的值是不可改变的。这就意味着它们通过hash 算法得到的值总是一个值。     作为字典键值的一个必备条件, 键值必须是可哈希的对象,元 组变量符合这个标准,而列表变量就不行。         >>> tk1 = ([],)          >>> tk1          ([],)          >>> dd1 = {tk1:1}          Traceback (most recent call last):            File "<stdin>", line 1, in <module>          TypeError: unhashable type: 'list'          >>> tk2 = (None,)          >>> tk2          (None,)          >>> dd2 = {tk2:2}          >>> dd2[tk2]          2          >>>     核心笔记:列表 VS 元组          一个经常会被问到的问题是,"为什么我们要区分元组和列表变量?"这个问题也可以被表      述为“我们真的需要两个相似的序列类型吗?”,一个原因是在有些情况下,使用其中的一种类      型要优于使用另一种类型。          最好使用不可变类型变量的一个情况是,如果你在维护一些敏感的数据,并且需要把这些      数据传递给一个并不了解的函数(或许是一个根本不是你写的API),作为一个只负责一个软件      某一部分的工程师,如果你确信你的数据不会被调用的函数篡改,你会觉得安全了许多。      一个需要可变类型参数的例子是,如果你在管理动态数据集合时。你需要先把它们创建出      来,逐渐地或者不定期的添加它们,或者有时还要移除一些单个的元素。这是一个必须使用可      变类型对象的典型例子。幸运的是,通过内建的list()和tuple()转换函数,你可以非常轻松      的在两者之间进行转换.          list()和tuple()函数允许你用一个列表来创建一个元组,反之亦然.如果你有一个元组变      量,但你需要一个列表变量因为你要更新一下它的对象,这时list()函数就是你最好的帮手.如      果你有一个列表变量,并且想把它传递给一个函数,或许一个API,而你又不想让任何人弄乱你      的数据,这时tuple()函数就非常有用。 6.19 相关模块                                      6.20 拷贝Python 对象      浅拷贝和深拷贝     浅拷贝         当你创建一个 对象,然后把它赋给另一个变量的时候,Python 并没有拷贝这个对象,而是拷贝了这个对象的引用。             序列类型对象的浅拷贝是默认类型拷贝,并可以以下几种方式实施:             (1)完全切片操作[:],             (2) 利用工厂函数,比如list(),dict()等,             (3)使用copy 模块的copy 函数.                 >>> person = ['name',['savings',100.00]]                  >>> hubby = person[:] #slice copy                  >>> wife = list(person) #fac func copy                  >>> [id(x) for x in person, hubby, wife]                  [38947976L, 39059528L, 38386248L]                  >>> hubby[0] = 'joe'                  >>> wife[0] = 'jane'                  >>> hubby,wife                  (['joe ', ['savings', 100.0]], ['jane ', ['savings', 100.0]] )                 >>> hubby[1][1] = 50.00                  >>> hubby,wife                  (['joe', ['savings', 50.0]], ['jane', ['savings', 50.0]])                  >>>     深拷贝          要得到一个完全拷贝或者说深拷贝--创建一个新的容器对象, 包含原有对象元素(引用)全新拷贝的引用--需要copy.deepcopy()函数.             >>> person = ['name',['saving',100.00]]              >>> hubby = person              >>> import copy              >>> wife = copy.deepcopy(person)              >>> [id(x) for x in person, hubby, wife]              [39046152L, 39046152L, 31307144L]              >>> hubby[0] = 'joe'              >>> wife[0] = 'jane'              >>> hubby,wife              (['joe', ['saving', 100.0]], ['jane', ['saving', 100.0]])              >>> hubby[1][1] = 50.00              >>> hubby,wife              (['joe', ['saving', 50.0]], ['jane', ['saving', 100.0]])              >>>     关于拷贝操作的警告         第一, 非容器类型(比如数字,字符串和其他"原子"类型的 对象,像代码,类型和xrange 对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成的.         第二, 如果元组变量只包含原子类型对象,对它的深拷贝将不会进行.如果我们把账户信息改成元组类型,那么即便按我们的要求使用深拷贝操作也只能得到一个浅拷贝:     核心模块: copy          浅拷贝和深拷贝操作都可以在copy 模块中找到.其实copy 模块中只有两个函数可用:copy()进行浅拷贝操作,而deepcopy()进行深拷贝操作. 6.21 序列类型小结     序列类型为数据的顺序存储提供了几种机制.     字符串是最常用的数据载体,无论是用于给用 户显示,存贮到硬盘,通过网络传输,还是作为一个多源信息的容器.     列表和元组提供了容器存储能力,允许简单的操作和访问多个对象,无论它们是Python 的对象还是用户自定义的对象.     单一元素或一组元素可以通过持续有序地索引偏移进行切片操作来访问.总之,这些数据类型为你的Python 开发环境提供了灵活而易用的存贮工具.                    
关键词:字符 字符串 列表