本章将详细介绍已经学习的一些内容,并增加一些新的内容。

5.1。更多关于列表

列表数据类型有更多的方法。以下是列表对象的所有方法:

list.append
将项目添加到列表的末尾。相当于。a[len(a):] = [x]
list.extend可迭代
通过附加iterable中的所有项来扩展列表。相当于 。a[len(a):] = iterable
list.inserti
在一个给定的位置插入一个项目。第一个参数是要插入的元素的索引,所以插入列表的前面,等同于。a.insert(0, x)a.insert(len(a), x)a.append(x)
list.remove
从列表中删除值为x的第一个项目。如果没有这样的项目,这是一个错误。
list.pop
删除列表中给定位置的项目,然后返回。如果没有指定索引,则a.pop()删除并返回列表中的最后一个项目。(周围的方括号在方法签名表示这个参数是可选的,不是说你应该在该位置键入方括号,你会经常看到这个符号在Python库参考。)
list.clear
删除列表中的所有项目。相当于。del a[:]
list.index[start [end 
在值为x的第一个项目的列表中返回从零开始的索引。提出了ValueError如果没有这样的项目。

可选参数startend被解释为切片符号,并用于限制搜索到列表的特定子序列。返回的索引是相对于整个序列的开始而不是起始参数计算的。

list.count
返回x出现在列表中的次数。
list.sortkey = Nonereverse = False 
对列表中的项目进行排序(参数可以用于排序自定义,请参阅sorted()他们的解释)。
list.reverse
颠倒列表中的元素。
list.copy
返回列表的浅表副本。相当于a[:]

一个使用大多数列表方法的例子:

>>>

>>> fruits  =  [ 'orange'  'apple'  'pear'  'banana'  'kiwi'  'apple'  'banana' ] 
>>> fruits 计数'苹果' 
2 
>>> 水果计数'橘' 
0 
>>> 水果指数'香蕉' 
3 
>>> 水果   #寻找下一个香蕉开始一个位置4 
6 
>>> 水果reverse ()
>>> fruits 
['banana','apple','kiwi','banana','pear','apple','orange'] 
>>> fruits 附加'葡萄' 
>>> 水果
['香蕉','苹果','猕猴桃','香蕉','梨','苹果','橙','葡萄'] 
>>> 水果sort ()
>>> fruits 
['apple','apple','banana','banana',' 
葡萄','奇异果','橙','梨'] >>> 水果pop ()
'pear'

您可能已经注意到,方法一样insertremove或者sort只修改列表没有返回值印刷-它们返回的默认 None[1] 这是Python中所有可变数据结构的设计原则。

5.1.1。使用列表作为堆栈

列表方法使得使用列表作为堆栈非常容易,其中添加的最后一个元素是检索的第一个元素(“后进先出”)。要将项目添加到堆栈的顶部,请使用append()。要从堆栈顶部检索项目,请使用pop()没有显式索引的项目。例如:

>>>

>>> 堆栈 =  [ 3  4  5 ] 
>>> 追加6 
>>> 堆栈追加7 
>>> 堆栈
[3,4,5,6,7] 
>>> 堆栈pop ()
7 
>>> stack 
[3,4,5,6] 
>>> stack pop ()
6 
>>> stack pop ()
5 
>>> stack 
[3,4]

5.1.2。使用列表作为队列

也可以使用列表作为队列,其中第一个添加的元素是检索到的第一个元素(“先入先出”); 然而,列表并不是有效的。尽管从列表末尾的附加和弹出快速,但是从列表的开始处插入或弹出很慢(因为所有其他元素必须被移位一个)。

要实现一个队列,使用collections.deque它被设计为快速追加和从两端弹出。例如:

>>>

>>> from  collections  import  deque 
>>> queue  =  deque ([ “Eric”  “John”  “Michael” ])
>>> queue append “Terry”            #Terry到达
>>> 队列追加“Graham”           #Graham到达
>>> 队列popleft ()                 #第一个到达现在离开
'埃里克' 
>>> 队列                 
'John' 
>>> 队列                           #剩余队列按到达顺序
deque(['Michael','Terry','Graham'))

5.1.3。列表理解

列表解析提供了一个简洁的方式来创建列表。常见的应用是创建新的列表,其中每个元素是一些操作应用到另一个序列的每个成员或迭代的结果,或者创建满足一定条件的那些元素的子序列。

例如,假设我们要创建一个正方形列表,如:

>>>

>>> 正方形 =  [] 
>>> 对于 X   范围10 ):
...     正方形append x ** 2 
... 
>>> squares 
[0,1,4,9,16,25,36,49,64,81]

请注意,这会创建(或覆盖)x循环完成后仍然存在的变量。我们可以使用下列方法计算没有任何副作用的方格列表:

square  =  list map lambda  x  x ** 2  range 10 )))

或者等价地:

正方形 =  [ X ** 2   X   范围10 )]

这更简洁可读。

列表理解由括号组成,括号中包含一个表达式后跟一个for子句,然后是零个或多个forif 子句。结果将成为一个新的列表,由评估表达式在后面的条款forif条款。例如,如果这个listcomp不相等,那么这个listcomp将两个列表的元素组合在一起:

>>>

>>> [(X  ÿ   X   [ 1 2 3 ]   ÿ   [ 3 1 4 ]  如果 X  !=  ÿ ] 
[(1,3),(1,4),(2 ,3),(2,1),(2,4),(3,1),(3,4)]

这相当于:

>>>

>>> 梳子 =  [] 
>>> 对于 X   [ 1 2 3 ]:
...      Ý   [ 3 1 4 ]:
......         如果 X  !=  ÿ 
...             梳子追加((X  ÿ ))
... 
>>> 梳子
[(1,3),(1,4),(2,3),(2,1),(2,4),(3,1 ),(3,4)]

请注意,这两个代码片段中的for和命令的顺序if是相同的。

如果表达式是一个元组(例如,在前面的例子中),它必须加上括号。(x, y)

>>>

>>> VEC  =  [ - 4  - 2  0  2  4 ] 
>>> #创建一个新的列表与所述值加倍
>>> [ X * 2   X   VEC ] 
[-8,-4,0 ,4,8] 
>>> #过滤列表以排除负数
>>> [ x, 对于 vec中的x   如果x > = 0 ] [ 0,2,4  ] >>> #对所有元素应用一个函数> >>[   


ABS X   X   VEC ] 
[4,2,0,2,4] 
>>> #调用每个元件上的方法
>>> freshfruit  =  [ '香蕉'  '罗甘莓'  '西番莲' ] 
> >> [ 武器() 用于 武器  freshfruit ] 
[ '香蕉', '罗甘莓', '西番莲'] 
>>> #创建的2元组等(号码,正方形)的列表
>>> [(X   对于 X   范围6 )] 
[(0,0),(1,1),(2,4),(3,9),(4,16),(5,25)] 
>>> #的元组必须被括号,否则产生一个错误
>>> [ X  X ** 2   X   范围6 )] 
  文件“<标准输入>”,第1行,在<模块> 
    [X,X ** 2为中的x范围(6)] 
               ^ 
语法错误:无效的语法
>>> #弄平使用listcomp列表带有两个'关于' 
>>> VEC  =  [[ 1 2 3 ], [ 4 5 6 ], [ 7 8 9 ]] 
>>> [ NUM   ELEM   VEC   NUM   ELEM ] 
[1,2,3,4,5,6,7,8,9]

列表解析可以包含复杂表达式和嵌套函数:

>>>

>>>  数学 进口 PI 
>>> [ STR PI  ))    范围1  6 )] 
[ '3.1', '3.14', '3.142', '3.1416', '3.14159' ]

5.1.4。嵌套列表理解

列表理解中的初始表达式可以是任意的表达式,包括另一个列表理解。

考虑以下3个4列表长度为4的列表实现的例子:

>>>

>>> 矩阵 =  [ 
...     [ 1  2  3  4 ],
...     [ 5  6  7  8 ],
...     [ 9  10  11  12 ],
... ]

以下列表理解将转置行和列:

>>>

>>> [[ row [ i ]  for  row  in  matrix ]  for  i  in  range 4 )] 
[[1,5,9],[2,6,10],[3,7,11],[4, 8,12]]

正如我们在上一节看到的那样,嵌套的listcomp是在for它后面的上下文中进行求值的,所以这个例子相当于:

>>>

>>> 转置 =  [] 
>>>    范围4 ):
...     转置追加([ [ ]     矩阵])
... 
>>> 转置
[[1,5,9],[2,6,10],[3,7,11],[4,8 12]

这反过来又是一样的:

>>>

>>> 换位 =  [] 
>>> 用于   范围4 ):
...     #下面3行执行嵌套listcomp 
...     transposed_row  =  [] 
...        矩阵
...         transposed_row 附加[ i ])
...     转置append transposed_row 
... 
>>> transposed 
[[1,5,9],[2,6,10],[3,7,11],[4,8,12]]

在现实世界中,您应该更喜欢内置函数来处理复杂的流程语句。这个zip()函数对于这个用例来说可以做的很好:

>>>

>>> list zip * matrix ))
[(1,5,9),(2,6,10),(3,7,11),(4,8,12)]

有关此行中星号的详细信息,请参阅解包参数列表

5.2。该del声明

有一种方法可以从列表中删除一个项目给定的索引,而不是它的值:del声明。这与pop()返回值的方法不同。该del语句也可用于从列表中删除切片或清除整个列表(我们之前通过将空列表分配给切片)。例如:

>>>

>>> 一个 =  [ - 1  1  66.25  333  333  1234.5 ] 
>>> 德尔 一个[ 0 ] 
>>> 一个
[1,66.25,333,333,1234.5] 
>>> 德尔 一个[ 2 4 ] 
>>> a 
[1,66.25,1234.5] 
>>> del  a [:] 
>>> a 
[]

del 也可以用来删除整个变量:

>>>

>>> del  a

以后引用这个名字a是一个错误(至少在另外一个值被分配给它的时候)。稍后我们会找到其他用途del

5.3。元组和序列

我们看到列表和字符串有很多共同的属性,比如索引和切片操作。它们是序列数据类型的两个示例(请参见 序列类型 – 列表,元组,范围)。由于Python是一种不断发展的语言,因此可能会添加其他序列数据类型。还有另一个标准的序列数据类型: 元组

元组由多个用逗号分隔的值组成,例如:

>>>

>>> 牛逼 =  12345  54321  '你好!' 
>>> [ 0 ] 
12345 
>>> 
(12345,54321, '你好!')
>>> #元组可以被嵌套:
... Ù  =   1  2  3  4  5 
> >> u 
((12345,54321,'hello!'),(1,2,3,4,5))
>>> #元组是不可变的:
... t [ 0 ]  =  88888
回溯(最近通话最后一个):
  文件“<标准输入>” ,线1 ,在<模块> 
类型错误“元组”对象不支持项目分配
>>> #但可以包含可变对象:
... v  =  ( [ 1  2  3 ], [ 3  2  1 ])
>>> v 
([1,2,3],[3,2,1])

正如你所看到的,在输出中元组总是被括在圆括号中,这样嵌套的元组被正确解释; 他们可能是有或没有包围括号的输入,尽管通常括号是必要的(如果元组是更大的表达的一部分)。不能分配给元组的各个项目,但是可以创建包含可变对象(例如列表)的元组。

尽管元组可能看起来与列表类似,但是它们通常用于不同的情况和不同的目的。元组是不可变的,并且通常包含通过解包(参见本节后面的内容)或索引(或甚至通过属性)访问的异构元素序列namedtuples。列表是可变的,它们的元素通常是同构的,并且通过遍历列表来访问。

一个特殊的问题是包含0或1项的元组的构造:语法有一些额外的怪癖,以适应这些。空元组由一对空括号构成; 带有一个项目的元组是通过跟随一个带有逗号的值来构造的(这不足以将单个值括在圆括号中)。丑,但有效。例如:

>>>

>>> empty  =  ()
>>> singleton  =  'hello'     #< - 注意尾随逗号
>>> len 
0 
>>> len singleton 
1 
>>> singleton 
('hello',)

该语句是一个元组打包的例子:值,并且被打包在一个元组中。反向操作也是可能的:t = 12345, 54321, 'hello!'1234554321'hello!'

>>>

>>> x  y  z  =  t

这被称为,适当的,序列拆包,并适用于任何序列在右侧。序列拆包要求在等号左侧的变量数量与序列中的元素数量相同。请注意,多个赋值实际上只是元组打包和序列解包的组合。

5.4。集

Python还包含一个数据类型的集合。一个集合是一个没有重复元素的无序集合。基本用途包括成员资格测试和消除重复条目。Set对象也支持像union,intersection,difference和symmetric difference这样的数学运算。

大括号或set()功能可用于创建集。注意:要创建一个空的集合,你必须使用set(),而不是{}; 后者创建一个空字典,我们将在下一节讨论一个数据结构。

这里是一个简短的演示:

>>>

>>> basket  =  { 'apple'  'orange'  'apple'  'pear'  'orange'  'banana' } 
>>> print basket                       #显示重复项已被移除
{'orange','香蕉”,‘鸭梨’,‘苹果’} 
>>> ‘橙色’   篮子                 #快速检测成员
真正
>>> ‘马唐’   篮下


>>> #演示对两个单词的唯一字母进行设置操作
... 
>>> a  =  set 'abracadabra' 
>>> b  =  set 'alacazam' 
>>> a                                   #在一个
{'a ','r','b','c','d'} 
>>> a  -  b                               
a 中的一个但不是b的字母{'r','d','b'} 
>>> a  |  b                               在a或b或二者#字母
{ '一个', 'C', 'R', 'd', 'B', 'M', 'Z','
                                

 在a或b中a ^  b                               #个字母,但不是两个
{'r','d','b','m','z','l'}

列表解析类似,集合解析也被支持:

>>>

>>> 一个 =  { X   X   '胡言乱语'  如果 X  不是  'ABC' } 
>>> 一个
{ 'R', 'd'}

5.5。字典

Python中内置的另一个有用的数据类型是字典(参见 映射类型 – 字典)。字典有时在其他语言中被称为“联想记忆”或“联想阵列”。不同于以数字范围索引的序列,字典是由索引的,可以是任何不可变的类型; 字符串和数字始终可以是键。如果元组只包含字符串,数字或元组,则可以用作关键字; 如果元组直接或间接包含任何可变对象,则不能将其用作关键字。你不能用链表做关键字,因为链表可以用索引赋值,切片赋值,或类似的方法进行修改append()和 extend()

最好将字典视为无序的键值对,并要求键是唯一的(在一个字典中)。一对大括号创建一个空的字典:{}。在大括号内放置一个以逗号分隔的键:值对列表,将初始键:值对添加到字典中; 这也是词典写在输出上的方式。

字典上的主要操作是用某个键存储一个值,并提取给定键的值。也可以使用删除键:值对del。如果使用已在使用的密钥进行存储,则与该密钥关联的旧值将被遗忘。使用不存在的键提取值是错误的。

list(d.keys())在字典上执行将以任意顺序返回字典中使用的所有键的列表(如果您想对其进行排序,则只需使用 sorted(d.keys()))。[2] 要检查单个密钥是否在字典中,请使用in关键字。

这是一个使用字典的小例子:

>>>

>>> 电话 =  { '插孔'  4098  'SAPE'  4139 } 
>>> 电话[ '圭' ]  =  4127 
>>> 电话
{ 'SAPE':4139, '圭多':4127, '插孔': 4098 
>>> tel [ 'jack' ] 
4098 
>>> del  tel [ 'sape' ] 
>>> tel [ 'irv' ]  =  4127 
>>> tel 
{'guido':4127,'irv':4127,'jack':4098} 
>>> list tel ())
[ 'IRV', '圭多', '插孔'] 
>>> 排序电话())
[ '圭', 'IRV', '插孔'] 
>>> '圭'   电话

>>> “杰克”  不是  电话

dict()构造直接从键-值对的序列构建字典:

>>>

>>> dict ''sape'  4139 ), 'guido'  4127 ), 'jack'  4098 )])
{'sape':4139,'jack':4098,'guido':4127}

此外,可以使用dict comprehensions从任意键和值表达式创建字典:

>>>

>>> { X  X ** 2   X   2  4  6 )} 
{2:4,4:16,6:36}

当键是简单字符串时,使用关键字参数指定对有时更容易:

>>>

>>> dict sape = 4139  guido = 4127  jack = 4098 
{'sape':4139,'jack':4098,'guido':4127}

5.6。循环技巧

在循环字典时,可以使用该items()方法同时检索关键字和相应的值。

>>>

>>> 骑士 =  { 'gallahad'  '纯'  '循环'  '勇敢的' } 
>>>  ķ  v   骑士items ():
...     print k  v 
... 
gallahad纯粹的
知更鸟是勇敢的

循环一个序列时,可以使用该enumerate()函数同时检索位置索引和相应的值。

>>>

>>> for  i  v  in  enumerate ([ 'tic'  'tac'  'toe' ]):
...     print i  v 
... 
0 tic 
1 tac 
2 toe

要同时循环两个或更多个序列,可以将该条目与该zip()函数配对。

>>>

你叫什么名字?这是兰花。    
    
     
     


你的追求是什么?这是圣杯。
什么是你最喜欢的颜色?它是蓝色的。

要反向循环序列,首先指定正向序列,然后调用该reversed()函数。

>>>

>>> 用于   逆转范围1  10  2 )):
...     打印
... 
9 
7 
5 
3 
1

要按照排序顺序循环序列,请使用sorted()返回新排序列表的功能,同时保持源不变。

>>>

>>> basket  =  [ 'apple'  'orange'  'apple'  'pear'  'orange'  'banana' ] 
>>> for  f  in  sort set basket )):
...     print f 
... 
苹果
香蕉
橙子

当你循环播放的时候,有时候会更改列表。然而,创建一个新的列表通常更简单,更安全。

>>>

>>> 进口 数学
>>> raw_data  =  [ 56.2  浮子'的NaN' ), 51.7  55.3  52.5  浮子'的NaN' ), 47.8 ] 
>>> filtered_data  =  [] 
>>>    raw_data 
...     如果 不是 数学isnan value ):
...         filtered_data 附加
...
>>> filtered_data 
[56.2,51.7,55.3,52.5,47.8]

5.7。更多关于条件

whileif语句中使用的条件可以包含任何运算符,而不仅仅是比较。

比较运算符in并检查序列中是否出现值(不会发生)。运算符并比较两个对象是否真的是同一个对象; 这只对像列表这样的可变对象很重要。所有比较运算符具有相同的优先级,低于所有数值运算符。not inisis not

比较可以链接。例如,测试是否小于,并且相等。a < b == cabbc

比较可以使用布尔运算符进行组合andor,和一个比较的结果(或任何其它的布尔表达式的)可以与否定not。这些比比较运营商的优先级低; 在他们之间,not有最高的优先和or最低的,所以相当于。一如往常,括号可以用来表达所需的组成。A and not B or C(A and (not B)) or C

布尔运算符andor被所谓的短路 运营商:从左至右他们的论点进行评估,评估一旦结果被确定停止。例如,如果是AC为真,但B为假,则不评估表达式 。当用作普通值而不是布尔值时,短路运算符的返回值是最后一次评估的参数。A and B and CC

可以将比较结果或其他布尔表达式分配给变量。例如,

>>>

>>> 字符串1  字符串2  STRING3  =  ''  '特隆赫姆'  '锤舞' 
>>> non_null  =  字符串1   字符串2   STRING3 
>>> non_null 
'特隆赫姆'

请注意,在Python中,与C不同,赋值不能在表达式内发生。C程序员可能会为此抱怨,但它避免了C程序中遇到的一类常见问题:打算=在表达式中输入表达式==

5.8。比较序列和其他类型

序列对象可以与具有相同序列类型的其他对象进行比较。比较使用词典排序:首先比较前两个项目,如果它们不同则确定比较的结果; 如果它们相等,则比较下两项,等等,直到任何一个序列被耗尽为止。如果两个要比较的项目本身是同一类型的序列,那么递归地进行字典比较。如果两个序列的所有项目比较相等,则序列被认为是相等的。如果一个序列是另一个序列的初始子序列,则较短的序列是较小(较小)的序列。字符串的字典排序使用Unicode代码点号来排列单个字符。一些相同类型的序列之间的比较的例子:

1  2  3               <  1  2  4 
[ 1  2  3 ]               <  [ 1  2  4 ] 
'ABC'  <  'C'  <  '帕斯卡 <  'Python的
1  2  3  4            <  1  2  4 
1  2                  < 1  2  - 1 
1  2  3              ==  1.0  2.0  3.0 
1  2  'AA'  'AB' ))   <  1  2  'ABC'  'a' ), 4 

请注意,比较不同类型的对象具有<>为法律规定,对象有适当的比较方法。例如,混合数字类型根据它们的数值进行比较,所以0等于0.0等。否则,解释器将提出TypeError异常,而不是提供任意排序。

脚注

[1] 其他语言可能会返回突变的对象,这允许方法链接,如d->insert("a")->remove("b")->sort();
[2] 调用d.keys()将返回一个字典视图对象。它支持像成员测试和迭代这样的操作,但是它的内容并不独立于原来的字典 – 这只是一个视图