您的位置:首页 > 编程语言 > Python开发

Python学习教程(二)——序列之列表和元组

2017-10-27 23:04 555 查看

1. 序列

1.1. 序列概览

  在Python中,最基本的数据结构是序列(sequence),序列中的每一个元素被分配一个序号——即元素的位置,也成为索引,从0开始计数。Python中有6种内建的序列:列表、元组、字符串、Unicode字符串、buffer对象、xrange对象

  所谓“序列概览”讲的是所有序列类型都通用的操作。

  列表和元组的主要区别:列表可以修改,元组则不能。

  下面就是一个序列的例子:

ylh = ['yangliehui',28]


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

>>> ylh = ['yangliehui',28]
>>> zs = ['zhangsan',30]
>>> names = [ylh,zs]
>>> names
[['yangliehui', 28], ['zhangsan', 30]]


1.2. 通用序列操作

1.2.1. 索引

  序列中所有的编号都是从0开始的,比如下面的字符串就是为字符组成的序列。

>>> greeting = 'Hello'
>>> greeting[0]
'H'


  序列的索引可以是从左向右,此时第一个是0,往右加1;可以可以是从右向左,最右边-1开始,往左减1;如下:

>>> greeting = 'Hello!'
>>> greeting[-1]
'!'


  序列字面值可以直接使用索引而不需要一个变量引用(这适用于其他序列而不仅限于字符串),如下:

>>> 'Hello!'[0]
'H'
>>> 'Hello!'[-1]
'!'


  也可以直接对返回结果操作:

>>> year = raw_input('Year=')[3]
Year=2017
>>> year
'7'


1.2.2. 分片

  与索引类似,索引用来访问单个元素,而分片用来访问一定范围内的元素。格式如下:

  [参数1:参数2]:参数1表示要提取的第一个元素的编号,第二个参数表示分片之后剩余部分中第一个元素的标号。

>>> str = 'abcdefg'
>>> str[1:5]
'bcde'


  上面的代码可以用下图表示:



>>> str = 'abcdefg'
>>> str[-6:-2]
'bcde'


  上面的代码可以用下图表示:



  我们要注意下面的情况,如果自左向右取数,索引7指向的元素并不存在,但却是在最后一个元素之后,是没有问题的。但是如果从结尾自右向左取数,显然第二个参数写-1或写0都是不对的。尤其例子中[-6:0]的写法,只要顺序写反了都会返回空字符串。

>>> str = 'abcdefg'
>>> str[1:7]
'bcdefg'


  上面的代码可以用下图表示:



>>> str = 'abcdefg'
>>> str[-6:-1]
'bcdef'
>>> str[-6:0]
''


  上面的代码可以用下图表示:



  那么上述描述的情况就无解了吗?其实我们可以有另一种写法,空一个参数:

>>> str = 'abcdefg'
>>> str[-6:]
'bcdefg'
>>> str[1:]
'bcdefg'


  两个参数都写空也是可以的,这样将会返回整个序列:

>>> str = 'abcdefg'
>>> str[:]
'abcdefg'


  现在介绍分片的第三个参数,步长,看一段程序:

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


以上就是步长,当步长为2时会跳过一个元素;

  步长不能为0,但是步长可以为负数,这时从从右向左取数:

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


但这里要注意,如果步长为负数,那么第一第二个参数提取元素的顺序也是倒序的,如下:

>>> numbers=[1,2,3,4,5,6,7,8,9,10]
>>> numbers[8:3:-1] #我们看到参数的顺序是先8后3
[9, 8, 7, 6, 5]
>>> numbers[10:0:-2] #我们看到参数的顺序是先10后0
[10, 8, 6, 4, 2]
>>> numbers[0:10:-2] #反过来试试?发现顺序错误,返回空字符串
[]
>>> numbers[5::-2]
[6, 4, 2]
>>> numbers[:5:-2]
[10, 8]


1.2.3. 序列相加

  序列相加即是连接操作:

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


两种类型相同的序列才可以相加,所有上述[1,2,3]+’World!’报错。

1.2.4. 序列乘法

  我们先来看一个例子:

>>> 'python'*5
'pythonpythonpythonpythonpython'
>>> [23]*4
[23, 23, 23, 23]


  None是一个Python的内建值,表示“什么也没有”。初始化一个长度为10的列表:

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


1.2.5. 成员资格

  in运算符:检查一个值是否在序列中;

>>> permissions = 'rw'
>>> 'w' in permissions
True
>>> 'x' in permissions
False
>>> user = ['mlh','foo','bar']
>>> raw_input('Enter your user name:') in user
Enter your user name:mlh
True
>>> subject = '$$$ Get rich now!!! $$$'
>>> '$$$' in subject
True


  对于字符串,in可以查找子字符串:

>>> str = 'hello'
>>> 'hel' in str
True


1.2.6. 长度、最小值、最大值

  len、min、max函数。

>>> numbers=[100,34,678]
>>> len(numbers)
3
>>> max(numbers)
678
>>> min(numbers)
34
>>> max(2,3)
3
>>> min(9,3,4,5)
3


1.3. 序列涉及到的一些内建函数

1.3.1. reversed(seq)

对序列反向迭代。

与列表的reverse()方法不同,这个函数返回的是一个迭代器对象,对迭代器的使用这里不涉及,后续会有讲解。

>>> x = [1,2,3]
>>> y = reversed(x)
>>> list(y)
[3, 2, 1]


1.3.2. sorted(seq)

返回已排序的包含seq所有元素的列表。

与列表的sort()方法不同,列表sort方法是在原列表中修改,并且不会有返回值。而该函数不会对原列表修改,并且返回一个已经排序的列表副本:

>>> x = [6,5,2,8,9,2]
>>> y = sorted(x)
>>> x
[6, 5, 2, 8, 9, 2]
>>> y
[2, 2, 5, 6, 8, 9]


并且这个函数适用于所有的序列类型,并且总是返回一个列表:

>>> sorted('hello')
['e', 'h', 'l', 'l', 'o']
>>> sorted([4,1,2,7,0])
[0, 1, 2, 4, 7]
>>> sorted((4,1,2,6,1))
[1, 1, 2, 4, 6]


2. 列表

2.1. 列表的基础操作

列表是可变的——可以改变列表的内容。

2.1.1. 创建列表

  list函数:创建列表。适用于所有的序列类型,而不只是字符串。下面只是以字符串举例。由于字符串不能修改,所以可以根据字符串创建列表。利用list函数可以实现。

>>> list('hello')
['h', 'e', 'l', 'l', 'o']
>>> p1 = 'hello'
>>> list(p1)
['h', 'e', 'l', 'l', 'o']
>>> p3 = (432,643,745)
>>> list(p3)
[432, 643, 745]


  与之相反操作的函数为join。把列表转换为字符串:

>>> list_str = list('hello')
>>> ''.join(list_str)
'hello'


2.1.2. 改变列表

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


2.1.3. 删除元素

  del语句:

>>> names = ['zhangsan','lisi','yangliehui']
>>> del names[1]
>>> names
['zhangsan', 'yangliehui']


2.1.4. 分片赋值

>>> name = list('yangliehui')
>>> name
['y', 'a', 'n', 'g', 'l', 'i', 'e', 'h', 'u', 'i']
>>> name[7:]=list('yan')
>>> name
['y', 'a', 'n', 'g', 'l', 'i', 'e', 'y', 'a', 'n']


  在上面的例子中,name[7:]=’yan’ 这样写也会是同样的结果,因为string也是序列类型,当把string作为参数进行分片赋值给列表时会把字符串作为列表来处理,自动转换为列表。只是使用list函数转换一下更易读。看如下的例子:

>>> number = [None]*10
>>> number
[None, None, None, None, None, None, None, None, None, None]
>>> number[:] = '0123456789'
>>> number
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']


即使没有对’0123456789’做list转换,同样可以作为列表通过分片赋值。

  分片赋值的好处是可以使用与原序列不等长的序列将分片替换:

>>> name = list('ylh')
>>> name[0:] = list('yangliehui')
>>> name
['y', 'a', 'n', 'g', 'l', 'i', 'e', 'h', 'u', 'i']


上面的例子中,name有三个字符的序列,替换为了十个字符的序列。

  还可以插入新的元素:

>>> numbers = [1,5]
>>> numbers[1:1] = [2,3,4]
>>> numbers
[1, 2, 3, 4, 5]


  还可以删除元素:

>>> numbers
[1, 2, 3, 4, 5]
>>> numbers[1:4] = []
>>> numbers
[1, 5]


  还可以还步长配合使用:

>>> number = [1,2,3,4,5,6,7,8,9,10]
>>> number[::2] = ['a','b','c','d','e']
>>> number
['a', 2, 'b', 4, 'c', 6, 'd', 8, 'e', 10]


2.2. 列表常用方法

2.2.1. append

  列表末尾加新的对象;

>>> num = [1,2,3]
>>> num.append(4)
>>> num
[1, 2, 3, 4]
>>> str = ['a','b','c']
>>> str.append('d')
>>> str
['a', 'b', 'c', 'd']
>>>
>>> num.append('e')
>>> num
[1, 2, 3, 4, 'e']


注意可以追加不同类型的对象到列表中。

append是在原列表基础上修改列表内容。

2.2.2. count

  统计某个元素在列表中出现的次数。

>>> ['a','a','b','c'].count('a')
2
>>> x = [[1,2],1,1,[2,1,[1,2]]]
>>> x.count(1)
2
>>> x.count([1,2])
1


2.2.3. extend

  在列表末尾追加另一个序列中的多个值。

>>> a = [1,2,3,4]
>>> b = [5,6,7,8]
>>> a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6, 7, 8]


  它与原始的连接操作不同之处在于extend修改了被扩展的列表,而连接则返回一个全新的列表。

>>> a = [1,2,3,4]
>>> b = [5,6,7,8]
>>> a + b
[1, 2, 3, 4, 5, 6, 7, 8]
>>> a
[1, 2, 3, 4]


可以看到a的值并没有变化。

  当然我们也可以这样做,但是这只是创建了一个包含a和b的新列表,并重新赋给了a,不是一个原位置操作,不会修改原来的列表:

>>> a = a + b
>>> a
[1, 2, 3, 4, 5, 6, 7, 8]


所以效率不如extend。

  如果要实现和extend一样的原位置操作,可以如下:

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


这样做的缺点是可读性差,不如使用extend。

2.2.4. index

  某个值第一个匹配项的索引位置:

>>> names = ['zhangs','lis','ylh','wangw','ylh','jim']
>>> names.index('ylh')
2


  当没有找到时会报错:

>>> names.index('abc')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 'abc' is not in list


2.2.5. insert

  insert(index,object) index表示对象插入后在新列表中的索引位置。这种方式同样也是修改了现有的列表,而不是创建新的列表。

>>> number = [1,2,3,4,5,6,7,8]
>>> number.insert(3,'ins')
>>> number
[1, 2, 3, 'ins', 4, 5, 6, 7, 8]


  实现同样的功能,我们也可以使用分片:

>>> number = [1,2,3,4,5,6,7,8]
>>> number[3:3] = ['ins']
>>> number
[1, 2, 3, 'ins', 4, 5, 6, 7, 8]


注意,插入的必须是列表类型。 且可读性没有insert方法好。

2.2.6. pop

注意:它是唯一一个既能修改列表又返回新元素值(除了None)的列表方法

  pop方法类似入栈出栈中的出栈。当调用pop时返回最上面的列表元素,并修改了原来的原来的列表。如下:

>>> number = [1,2,3]
>>> number.pop()
3
>>> number
[1, 2]


  Python中并没有单独的入栈列表方法,但我们可以使用append来代替:

>>> number.append(3)
>>> number
[1, 2, 3]


  下面的例子中,程序先出栈返回3并修改了列表为[1,2],随后又出栈了出栈时返回的[3]。 所以得到的还是原来的列表。

>>> number
[1, 2, 3]
>>> number.append(number.pop())
>>> number
[1, 2, 3]


所以上面append和pop方法配合使用,实现了栈的结构——后进先出。

  其实pop方法还可以有参数的,参数表示要移除的元素在列表中的索引位置,如下:

>>> number = [1,2,3,4,5,6]
>>> number.pop(2)
3
>>> number
[1, 2, 4, 5, 6]


因此如果我们要实现一个queue,即先进先出,有以下两种方法:

1. insert(0,x) 和 pop() 配合使用:

>>> number = []
>>> number.insert(0,0)
>>> number.insert(0,1)
>>> number.insert(0,2)
>>> number.pop()
0
>>> number.pop()
1
>>> number.pop()
2
>>> number
[]


append 和 pop(0)配合使用:

>>> number = []
>>> number.append(0)
>>> number.append(1)
>>> number.append(2)
>>> number.pop(0)
0
>>> number.pop(0)
1
>>> number.pop(0)
2
>>> number
[]


2.2.7. remove

  移除列表中某个值的第一个匹配项:

>>> x = ['aaa','bb','aaa','cc']
>>> x.remove('aaa')
>>> x
['bb', 'aaa', 'cc']
>>> x.remove('dd')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list


只会移除第一个。并且当找不到参数内的元素时会提示错误。

它与pop不同的是,remove并不会返回被移除的元素值,它是没有返回值的。

相同的是,都在原列表上修改值;

2.2.8. reverse

  反向存放。

>>> x = [1,2,3,4]
>>> x.reverse()
>>> x
[4, 3, 2, 1]


原列表上修改,无返回值。

2.2.9. sort

  在原位置上对列表进行排序。并不是创建一个已排序的副本。该方法也没有返回值。

>>> x = [4,2,6,8,1,3,9]
>>> x.sort()
>>> x
[1, 2, 3, 4, 6, 8, 9]


关于排序的高级应用:

sort([func])

  func——指定比较函数,按照该函数的方法进行排序。

  这个指定的函数可以自建,比如我们定义一个函数compare(x,y),实现比如当x>y时返回1,当x

>>> x = [3,1,4,6,1,5,2,8]
>>> x.sort(cmp)
>>> x
[1, 1, 2, 3, 4, 5, 6, 8]


sort([key or reverse])

  参数key与cmp类似,需要提供一个排序过程中使用的函数。该函数不能直接确定对象的大小,而是为每个元素创建一个键,然后所有元素根据键来排序:

>>> x = ['aaaaaa','aa','a','aa']
>>> x.sort(key=len)
>>> x
['a', 'aa', 'aa', 'aaaaaa']


以元素的len为键,然后进行排序。

参数reverse,指定是否反向排序。

>>> x = [2,5,1,7,3,9,2,5]
>>> x.sort(reverse=False)
>>> x
[1, 2, 2, 3, 5, 5, 7, 9]
>>> x.sort(reverse=True)
>>> x
[9, 7, 5, 5, 3, 2, 2, 1]


3. 元组

序列的一种,不能修改。(其实字符串也是这样的)

3.1. 创建元组

>>> #直接逗号分隔
... 1,2,3
(1, 2, 3)
>>> #圆括号
... (1,2,3)
(1, 2, 3)
>>> #空元组
... ()
()
>>> #创建一个值的元组,我们发现必须要在元素后面加一个逗号
... 23,
(23,)
>>> (23)
23
>>> (23,)
(23,)


逗号的作用,一个逗号,结果千差万别:

>>> 3*(40+2)
126
>>> 3*(40+2,)
(42, 42, 42)


3.2. tuple函数

  与list函数类似,把序列类型值作为参数返回的是元组。

>>> tuple('abc')
('a', 'b', 'c')
>>> tuple([1,2,4])
(1, 2, 4)
>>> tuple((1,2,3))
(1, 2, 3)


元组可以使用与列表同样的分片操作,元组的分片还是元组,就像列表的分片还是列表一样。

>>> x = (1,2,3,4)
>>> x[1:3]
(2, 3)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python