四、列表和元祖

在python中,最基本的数据结构为序列。序列中的每个元素都有编号,即位置或索引。其中第一个元素的索引为0,第二个元素的索引为1,依次类推。从0开始指的是相对于序列开头的偏移量。用负索引表示序列末尾元素的位置。

序列概述

Python三种序列:列表、元祖、字符串。

列表和元祖的不同在于,列表是可以修改的,而元祖不可以。(想想为什么有的内置函数返回元祖的原因。)

在自己编写程序的时候,几乎所有的情况都可使用列表来代替元祖。一种情况例外,将元祖作用作字典键。(字典键是不允许修改的。)

列表用中括号来表示:

>>> lilei = ['lilei', 18]

序列还可以包含其他序列:

>>> lilei = ['lilei', 18]
>>> hanmeimei = ['hanmeimei', 13]
>>> jom = ['jom', 15]
>>> database = [lilei, hanmeimei, jom]
>>> database 
[['lilei', 18], ['hanmeimei', 13], ['jom', 15]]

  PS: Python支持一种数据结构的基本概念,名为容器。容器基本上就是可包含其他对象的对象。两种主要的容器是序列(列表、元素)和映射(如字典)。在序列中,每个元素都有编号,而在映射中,每个元素都有名字(键)。有一种既不是序列也不是映射的容器,它就是集合。

通用的序列操作

  有几种操作适用于所有的序列,包括索引、切片、相加、相乘成员资格检查。另外,Python中还提供了一些内置函数,可用于确定序列的长度以及找出序列中最大和最小的元素。

 PS:有一种操作暂时不讨论,迭代。对序列进行迭代意味着对其每个元素都执行特定的操作。

索引

  序列中所有的元素都有编号---从0开始递增。你可像下面这样使用编号来访问各个元素:

 

>>> msg = 'hello '
>>> msg[0]
'h'

 

  当使用负数索引的时,Python将从右(即元素的最后一个位置)开始往左数,因此-1是最后一个元素的位置。

>>> msg[-1]
' '

 对于字符串字面量(以及其他的序列字面量),可以直接对其执行索引操作,无需先将其赋给变量。这与先赋给变量再对变量执行索引操作的效果是一样的。

 

>>> 'hello'[1]
'e'

  如果函数调用返回一个序列,可直接对其执行索引操作。例如,如果你指向获取用户输入的年份的第四位,可像下面这样做:

>>> fourth = input("Year: ")[3]
Year: 2018
>>> fourth
'8'

  

切片

  除使用索引来访问元素外,还可使用切片来访问范围内的元素。为此,可使用俩个索引,并用冒号分割:

>>> msg = 'https://www.baidu.com'
>>> msg[12:17]
'baidu'

  第一个索引包含的是第一个元素的编号,但第二个索引是切片后余下的第一个元素标号。

>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> numbers[3:6]
[4, 5, 6]
>>> numbers[3:6][1]
5

  这貌似就出现一个问题,无法取出来最后一个元素。可以这样:

>>> numbers[7:0]

 步长

  执行切片操作的时候,可以显示或者隐式的指定起点和终点,如:

>>> msg = 'god is girl'
>>> msg[0:]
'god is girl'
>>> msg[:8]
'god is g'
>>> msg[:]   #复制整个序列
'god is girl'

  但通常忽略一个参数,即步长。在普通切片中,步长为1(即默认为1).可以显示的指定步长:

>>> msg[0::2]
'gdi il'

  还可以指定负数步长:

>>> msg[-1:0:-2] 'li id'

  序列相加

可使用加法运算符来拼接序列:

>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> 'hello' + ' ' + 'world!'
'hello world!'
>>> [1, 2, 3] + 'hello'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "str") to list

  PS:一般而言,不能拼接不同类型的序列。

相乘

将序列与数x相乘时,将重复这个序列x次来创建一个新序列:

>>> 'python' * 5
'pythonpythonpythonpythonpython'
>>> [1, 2] * 5
[1, 2, 1, 2, 1, 2, 1, 2, 1, 2]

空列表:

>>> list = []
>>> list
[]

包含10个‘什么都没有的值’的列表 

>>> list = [None] * 10
>>> list
[None, None, None, None, None, None, None, None, None, None]  

 

 成员资格

要检查特定的值是否包含在序列中,可使用运算符in:

>>> name = 'Ubuntu'
>>> '0' in name
False
>>> 'u' in name
True
>>> list = ['root', 'ubuntu', 'admin']
>>> 'root' in list
True
>>> 'roo' in list
False

  一般而言,运算符in检查指定对象是否是序列(或其他集合)的成员(即其中的一个元素),但是对于字符串来说,只有它包含的字符才是其成员或元素。

 

函数list实则是类)

>>> list('hello')
['h', 'e', 'l', 'l', 'o']

  可将任何序列作为list的参数。

>>> ''.join(['h', 'e', 'l', 'l', 'o'])
'hello'

修改列表

修改列表很容易,就如同普通的赋值,不同的是使用索引表示法给特定的元素赋值。

>>> x = [1, 2, 3, 4]
>>> x[1] = 1
>>> x
[1, 1, 3, 4]

PS:不能给部存在的元素赋值。

>>> x = [1, 2, 3, 4]
>>> x[4] = [5]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

删除元素

从列表删除元素很容易,只需要使用del语句即可。

>>> list = ['root', 'ubuntu', 'admin']
>>> del list[0]
>>> list
['ubuntu', 'admin']

给切片赋值

>>> name = list('root')
>>> name
['r', 'o', 'o', 't']
>>> name[2:] = list('ubuntu')
>>> name
['r', 'o', 'u', 'b', 'u', 'n', 't', 'u']
>>> name[2:] = '0'
>>> name
['r', 'o', '0']

  通过切片赋值,可将切片替换为长度与其不同的序列。(也就是包括不限于:可以指定位置插入)需要注意的是字符串没有这种操作。

>>> name = list('root')
>>> name[1:1] = 'ubuntu'
>>> name
['r', 'u', 'b', 'u', 'n', 't', 'u', 'o', 'o', 't']
>>> name = list('root')
>>> name[1] = 'ubuntu'
>>> name
['r', 'ubuntu', 'o', 't']

 删除切片

['r', 'ubuntu', 'o', 't']
>>> numbers = [1, 2, 3, 4, 5]
>>> numbers[1:4] = []
>>> numbers
[1, 5]

  PS:等效于del numbers[1:4]

列表的方法

方法是与对象(列表、数、字符串等)联系紧密的函数。通常这样调用方法:

object.method(arguments)

方法调用和函数调用很像,只是在方法名前加了对象和句点。

append 

方法append用于将一个对象附加到列表末尾。

>>> lst = [1, 2, 3]
>>> lst.append(4)
>>> lst
[1, 2, 3, 4]

 

clear

方法clear就地清空列表的内容。

>>> lst = [1, 2, 3]
>>> lst.clear()
>>> lst
[]

  这类似于切片赋值语句

lst[:] = []

  

copy

方法copy复制列表。常规复制,只是将另一个名称关联到列表。

>>> a = [1, 2, 3]
>>> b = a 
>>> b[1] = 4
>>> a
[1, 4, 3] 
1 >>> a = 'root'
2 >>> b = a
3 >>> a = 'ubuntu'
4 >>> b
5 'root'
参照和字符串的不同

要让a和b指向不同的列表,就必须将b关联到a的副本。

>>> a = [1, 2, 3]
>>> b = a.copy()
>>> b[1] = 4
>>> a
[1, 2, 3]

这类似于a[:]或list(a),他们也都是复制a

count

方法count计算指定元素在列表中出现了多少次。

>>> lst
['u', 'b', 'u', 'n', 't', 'u']
>>> lst.count('u')
3

extend 

方法extend让你同时将多个值附加到列表末尾。也就是,你可以使用一个列表来扩展另一个列表。

>>> a 
['1', '2', '3']
>>> b 
['4', '5', '6']
>>> a.extend(b)
>>> a
['1', '2', '3', '4', '5', '6']
>>> a = list('123')
>>> b = list('456')
>>> a + b
['1', '2', '3', '4', '5', '6']
>>> a 
['1', '2', '3']

  extend和拼接最大的区别在于,拼接不会改变原列表。需要重新用变量赋值。也可这样:

>>> a = list('123')
>>> b = list('456')
>>> a[len(a):] = b
>>> a
['1', '2', '3', '4', '5', '6']

index

方法index在列表中查找指定的元素第一次出现的索引。

>>> a
['1', '2', '3', '4', '5', '6']
>>> a.index('4')
3

  PS:需要注意的是,找不到会引发异常。

insert

方法insert用于将一个对象插入列表。

>>> a
['1', '2', '3', '4', '5', '6']
>>> a.insert(0, 'hello')
>>> a
['hello', '1', '2', '3', '4', '5', '6']
>>> a.insert(0, ['hello', 'world'])
>>> a
[['hello', 'world'], 'hello', '1', '2', '3', '4', '5', '6']

POP

方法pop从列表删除一个元素(默认为最后一个元素),并返回这一元素。

>>> a = list('hello')
>>> a.pop()
'o'
>>> a.pop(0)
'h'  

后进先出

>>> a = list('hello')
>>> a.append('world')
>>> a
['h', 'e', 'l', 'l', 'o', 'world']
>>> a.pop()
'world'
>>> a
['h', 'e', 'l', 'l', 'o']
>>> 

先进先出

可以用insert(0, ...)代替append

还可以使用pop(0)代替pop().

remove

方法remove用于删除第一个为指定值得元素。

>>> a
['u', 'b', 'u', 'n', 't', 'u']
>>> a.remove('u')
>>> a
['b', 'u', 'n', 't', 'u']

这只删除了为指定值得第一个元素,无法删除列表中其他指定得元素。

remove是就地修改且不返回值得方法之一。不同得是pop。

rverse

方法reverse按相反得顺序排列列表得元素。

>>> a = list('ubuntu')
>>> a.reverse()
>>> a
['u', 't', 'n', 'u', 'b', 'u']

要按相反得顺序迭代序列,可使用函数reversed.这个函数不返回列表,而是返回一个迭代器。

sort

方法sort用于对列表就地排序。

>>> a
['9', '5', '7', '4', '5', '1', '2']
>>> a.sort()
>>> a
['1', '2', '4', '5', '5', '7', '9']

PS:在除了pop方法意外,这些方法是没有返回值得。看下面:

>>> x
['9', '5', '4', '8', '7', '6', '2', '1', '2']
>>> y = x.sort()
>>> print(y)
None

可以用到函数sortd

>>> x = list('954876212')
>>> y = sorted(x)
>>> y
['1', '2', '2', '4', '5', '6', '7', '8', '9']
>>> sorted('hello')
['e', 'h', 'l', 'l', 'o']

这个函数可以用于任何序列。但总是返回一个列表

>>> sorted('hello ')
[' ', 'e', 'h', 'l', 'l', 'o']

高级排序

方法sort接受俩个可选参数:key和reverse。参数key需要接收一个用于排序的函数。然而,不会直接使用这个函数来判断一个元素是否比另一个元素小,而是使用它来为每一个元素创建一个键,再根据这些键对元素进行排序。因此,要根据长度对元素进行排序,可将参数key设置为函数len.

>>> name = ['root', 'mysql', 'mongodb', 'ubuntu']
>>> name.sort(key=len)
>>> name
['root', 'mysql', 'ubuntu', 'mongodb']

对于另一个关键字参数reverse,只需将其指定为一个真值(True或False),以指定是否按相反的顺序进行排序。

>>> name
['root', 'mysql', 'ubuntu', 'mongodb']
>>> name.sort(key=len, reverse=True)
>>> name
['mongodb', 'ubuntu', 'mysql', 'root']

  

元祖:不可修改的序列

与列表一样,元祖也是序列,唯一的差别在于元祖不能修改的,(字符串也不能修改),元祖语法简单,只要将一些值用,号分割,就能自动创建一个元祖。

>>> 1,2,3
(1, 2, 3)

空元祖

>>> ()
()

只有一个值的元祖,必须加上逗号

>>> (1)
1
>>> (1,)
(1,)

 函数tuple的工作原理和list一样,它将一个序列作为参数,并将其转换为元祖。如果参数已经是元祖就直接返回它。

元祖的切片也是元祖,就像列表的切片也是列表一样。

 

小结:

  序列是一种数据结构,其中的元素带编号(编号从0开始)。列表、字符串和元祖都属于序列,其中列表是可变的(你可修改其内容),而元祖和字符串是不可变的(一旦创建,内容就是固定的。).要访问序列的一部分,可使用切片操作:提供俩个指定切片起始和结束位置的索引。要修改列表,可给其元素赋值,也可使用切片语句给切片赋值。

  要确定特定的值是否包含在序列(或)其他容器中,可使用运算符in。

一些函数

len() #返回序列的长度
list() #将序列转换为列表,没有返回值
max() #返回序列或一组参数中的最大值
min() #返回序列或一组参数中的最小值
reversed() #反向迭代序列
sorted() # 返回有序列表
tuple() #将序列转换为元祖

posted on 2018-05-09 11:50  空舟  阅读(748)  评论(0编辑  收藏  举报

导航