序列概览
在Python中最基本的数据结构是序列(sequence)。序列共有6种类型,本章只重点讨论两种:列表和元组。该章的大致结构为:
- 通用序列操作
- 列表
- 元组
通用序列操作
所有的序列都能进行某些特定的操作,并且Python还带有计算长度、寻找最大和最小元素等功能的内建方法。
索引
序列总所有的元素都是带编号的,0表示从第一位开始,-1表示从最后一位开始。字符串就是一个由字符组成序列:
>>> greeting = "Hello"
>>> greeting[0]
'H'
>>> "Hello"[-1]
'o'
接下来该书实例给了一个小程序。当做练习个人简单把要求抽象一下,如果你也是同我一样刚刚入门Python可以试着自己编编看:
要求用户输入年、月(1-12)、日(1-31),然后按照形如:September 12th,2014 的格式输出构建的字符串。
如下是自己构建的一段代码以及相应的输入输出结果:
year = raw_input("Year:")
month = raw_input("Month(1-12):")
day = raw_input("Day(1-31):")
monthes = [
"January",
"February",
"March",
"April",
"Ma",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
]
#此处个人对英文位数的后缀表示法理解有偏差
days = ['st', 'rd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th'];
print monthes[int(month) - 1] + ' ' + day + days[int(day) - 1] + ',' + year
执行即可看到如下结果:
$ python sequencePractise.py
Year:2015
Month(1-12):1
Day(1-31):5
January 5th,2015
相比之教程上的代码,有些东西是可以改进的
(1)在英文表达习惯中第1-3的后缀是st、nd、rd, 其余则是th。比如:1st、12nd、23rd、15th。
(2)因为还没有学习分支(if else)所以这里用了一个长度为31的元组来用于后缀的使用。在Python中可以使用数组的拼接(跟Java和JavaScript比起来是新鲜的东西),如下:
days = ['st', 'nd', 'rd'] + 7*['th']+['st', 'nd', 'rd'] + 7*['th']+['st', 'nd', 'rd'] + 7*['th']+['st'] + ['st']
。
分片
分片简而言之就是指定开始索引、结束索引,然后得到一个子序列的操作。因为Python提供的分片操作非常灵活,一个一个介绍未必繁琐,下面列出书中的例子。可以先看输入猜测输出,再实际操作或者看结果来印证:
> numbers = [1,2,3,4,5,6,7,8,9,10]
> numbers[3:6]
[4, 5, 6] #注意索引为6的数字没有算在内
> numbers[-3:-1]
[8, 9]
> numbers[-3:0]
[] #第二个索引位置在第一个索引位置的前面
> numbers[-3:]
[8,9,10]
> numbers[:-3]
[1,2,3,4,5,6,7]
> numbers[:]
[1,2,3,4,5,6,7,8,9,10] # 结果相当于复制整个序列
> numbers[0:10:2]
[1, 3, 5, 7, 9]#第三个参数为步长
> numbers[8:3:-1]
[9, 8, 7, 6, 5]#步长可以为负数,索引大小也要反过来
> numbers[0:10:-2]
[]
> numbers[8::-2]
[9, 7, 5, 3, 1]
> numbers[5::-2]
[6, 4, 2]
> numbers[:5:-2]
[10,8]
#如上三个例子可以知道当其中一个索引没传值的时候,会根据步长的正负来设置默认的索引值。
并且注意:索引所指向的值不包含在切片结果中。
序列相加
> [1,2,3]+[4,5,6]
[1, 2, 3, 4, 5, 6]
> "Hello" + " World"
"Hello World"
> "Hello" + [1,2,3]
#结果:error,序列是分类型的,只有同类型的序列才能相加
乘法
数字乘以序列会生成一个新的序列,新序列中原先的内容被重复若干次。
> "Python"*3
"PythonPythonPython"
> [42]*5
[42, 42, 42, 42, 42]
是否包含成员
使用in运算符可以检测一个知道是否包含在序列中:
> permission = 'rw'
> 'w' in permission
True
> users = ['admin', 'root']
> raw_input('Enter your name:') in users
Enter your name:admin
True
长度、最小值和最大值
>>> numbers = [823, 428, 105]
>>> len(numbers)
3
>>> max(numbers)
823
>>> min(numbers)
105
>>> max(6,3,9,5)
9 #max、min也可以传入多个参数来获取最大最小值
列表
列表是可变的,并且有很多有用的、专门的方法。
list函数
函数不只是能对字符串使用,对所有类型的序列都能用。如下为根据字符串创建列表的例子:
>>> list("Hello")
['H', 'e', 'l', 'l', 'o']
基本的列表操作
列表是序列的一种,那么所有序列的操作都是用于列表,不同在于列表可以改变,该部分介绍改变列表的方法:元素赋值、元素删除、分片赋值、列表方法(并非所有列表方法都能改变列表)。
- 元素赋值
>>> x=[1,1,1]
>>> x[1]=2
>>> x
[1, 2, 1]
- 删除元素
>>> names = ['John', 'Swift', 'Skylar']
>>> del names[1]
>>> names
['John', 'Skylar']
- 切片赋值
>>> name = list('Perl')
>>> name[2:] = list('ar')
>>> name
['P', 'e', 'a', 'r']
>>> name = list('Perl')
>>> name[1:] = list('ython')
>>> name
['P', 'y', 't', 'h', 'o', 'n']
#在这里我们使用了不等长的列表进行切片替换。
>>> 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]
#这里起到了删除元素的作用。结合利用步长、负数可以有更多花样。
列表方法
- append
> [1,2,3].append(4)
[1,2,3,4]
- count
> ['to', 'be', 'or', 'not', 'to', 'be'].count('to')
2
- extend
a = [1, 2, 3]
b = [4, 5, 6]
a.extend(b)
a
[1, 2, 3, 4, 5, 6]
#可以看到a发生了改变,这是与直接使用a+b不同的。
当然该方法可以有别的如下两种替代办法:
> a = a + b
> a[len(a):] = b
- index
['to', 'be', 'or', 'not', 'to', 'be'].index('or')
2
- insert
>>> numbers = [1, 2, 3, 4]
>>> numbers.insert(2, 'three')
>>> numbers
[1, 2, 'three', 3, 4]
如上操作也等价于切片操作:
>>> numbers[3:3]=['three']
- pop
>>> numbers = [1,2,3]
>>> numbers.pop()
3
>>> numbers
[1, 2]
实现栈这种结构就可以通过结合使用(append和pop这两个方法来实现)。实现队列的话,则可以通过给pop和append添加为0的下标作为第一个参数。
- remove
>>> x = ['to', 'be', 'or', 'not', 'to', 'be']
>>> x.remove('be')
>>> x
['to', 'or', 'not', 'to', 'be']
如上移除的为第一个匹配项。
- reverse
>>> x = [1, 2, 3]
>>> x.reverse()
>>> x
[3, 2, 1]
- sort
>>> x = [4,7,2,1,7,9]
>>> x.sort()
>>> x
[1, 2, 4, 7, 7, 9]
该书在介绍如上绝大多数方法中都提到了(1)是否返回值(2)是否改变列表本身。个人觉得缺乏使用经验之前想要记忆住这些东西没有实际意义,真正使用的时候通过命令行简单测验就可以知道。
- 高级排序
如果希望按照自己定义的规则对列表进行排序,需要传递compare方法给sort,sort默认使用的是内建函数cmp(大于返回1,小于返回-1,等于返回0)。此处暂不详细叙述,原理跟Java应该是一样的。
>cmp(94, 39)
1
元组:不可变序列
如下列出了元组的常用表示法:
>1, 2, 3
(1, 2, 3)
>(1, 2, 3)
(1, 2, 3)
>()
()
> 42,
(42,)
> (42,) * 3
(42, 42, 42)
tuple函数
tuple是将序列转化为元组的函数,和列表总的list类似:
>>> tuple([1,2,3])
(1, 2, 3)
>>> tuple('hello')
('h', 'e', 'l', 'l', 'o')
元组基本操作
创建、访问、切片操作都和列表类似。
元组存在的意义
一般来说,列表能够满足绝大多数的需要。书中所提及元组存在的意义,现在还体会不深,暂且不管。