第二章 列表和元组
列表和元组区别:列表可以修改,二元组则不能
python的6种內建的序列:
列表和元组,字符串,Unicode字符串,buffer对象和xrange对象
元组与python的内部运作方式有关(內建函数可能返回元组)
几乎所有情况下列表可以代替元组,元组作为字典的键时除外
容器:包含其他对象的任意对象
两类主要的容器:序列(列表,元组)和映射(字典)
序列中的每个元素都有自己的编号,映射中的每一个元素都有一个名字(键)
set:既不是序列又不是映射的容器(见第十章)
2.2通用序列操作
包括:索引(indexing)、分片(sliceing)、加(adding)、乘(multiplying)以及检查某个元素是否属于某个序列,其次,计算序列长度,找出最大元素和最小元素的內建函数
2.2.1索引
months = [ #months(加s代表有多个月份)
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'Augest',
'Septempter',
'October',
'November',
'December'
]
#endings代表天数的后缀endings = ['st','nd','rd'] + 17* ['th'] \
+ [
'st','nd','rd'] + 7* ['th'] \
+ [
'st']
year =
input('Year:')
month =
input('Month(1-12):')
day =
input('Day(1-31):')
month_number =
int(month)#字符串转换为整型day_number = int(day)
#月份和天数减一,以获得正确的索引month_name =
months[month_number - 1]#下标从0开始day_name = day +
endings[day_number - 1] #数字联合后缀print(month_name,day_name,year)
2.2.2分片
[if !vml]
[endif]
图1 理解分片函数辅助图
使用捷径时(从指定索引处元素一直到最后),只需要指定开始元素
【代码】
#打印的首元素的下标要大于尾元素的下标numbers = [1,2,3,4,5,6,7,8,9,10]
print('指定元素:',numbers[3:6])
print('从倒数第三个元素到最后:',numbers[-3:])
print('从第一个元素到倒数第三个元素:',numbers[:-3])
print('从第一个元素到最后一个元素:',numbers[:])
【结果】
指定元素:[4, 5, 6]
从倒数第三个元素到最后:[8, 9, 10]
从第一个元素到倒数第三个元素:[1, 2, 3, 4, 5, 6, 7]
从第一个元素到最后一个元素:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
分片示例:
【代码】
url = input('Please
enter the URL:')
domain =url[
11:-4]
print('domain:',domain)
【结果】
Please enter the URL:http://www.python.org
domain: python
更大的步长:
【代码】
numbers = [0,1,2,3,4,5,6,7,8,9,10]
print(numbers[0:10:1])
print(numbers[0:10:2])
【结果】
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8]
也可以倒着来,那就是从右往左的顺序遍历,[A:B:C],则B>A,C<0(设C = -1)
序列为:B,B-1,B-2,…,A+1
【代码】
numbers = [0,1,2,3,4,5,6,7,8,9,10]
print(numbers[4:1:-1])
【结果】
[4, 3, 2]
2.2.3序列相加
列表和字符串无法连接在一起
【代码】
list = [1,2,3] + [4,5,6]
str =
'abc' + 'def'
print(list)
print(str)
print(list+ str)
【结果】
[1, 2, 3, 4, 5, 6]
abcdef
Traceback (most recent call last):
File"D:/python_file/20180113/test.py", line 5, in
print(list + str)
TypeError: can only concatenate list (not "str") to list
2.2.4乘法
用数字乘以一个序列会生成新的序列,原来的序列被重复n次
【代码】
print('python'* 5) #串乘print([42] * 5) #列表乘print((2,3) * 5) #元组乘
【结果】
pythonpythonpythonpythonpython
[42, 42, 42, 42, 42]
(2, 3, 2, 3, 2, 3, 2, 3, 2, 3)
【代码】
#有时需要使用一个值来代表空值,即None,用其来初始化一个长度为10的列表sequence = [None] * 10
print(sequence)
【结果】
[None, None, None, None, None, None, None, None, None, None]
[if !vml]
[endif]
【代码】
#打印一个字符组成的盒子,居中,且能够根据内容自动调整大小,只使用基本的算法,算出有多少空格、破折号等字符str = input('please input a
string:') #输入一个字符串screen = 80 #假定区域大小为80str_len = len(str) #输入串长度box_width = str_len +6 #盒子宽度left_margin_width = (80 - box_width) // 2 # //是整数除法运算符print('
' * left_margin_width +'+' + '-' * (box_width-2) + '+')
print(' ' * left_margin_width + '|' + ' ' * (box_width-2) + '|')
print(' ' * left_margin_width + '|' + ' ' * 2+str+ ' ' * 2 + '|')
print(' ' * left_margin_width + '|' + ' ' * (box_width-2) + '|')
print(' ' * left_margin_width + '+' + '-' * (box_width-2) + '+')
#使用print(A,B)的方式输出时,串A与串B之间会有一个空格,使用print(A+B)的方式输出时,A与B能够紧密地联系在一起
【结果】
please input a string:Hello, world!
+-----------------+
| |
| Hello, world! |
| |
+-----------------+
Process finished with exit code 0
2.2.5成员资格
【代码】
#检查一个值是否在序列中,使用in运算符,返回值是布尔型的,及True和Falsepermission = 'rw'
print('r' in permission)
print('x' in permission)
users = [
'mhl','foo','bar']
print( input("please
input a user:") in users )
subject =
'$$$ Get rich now!!!$$$'
print('$$$' in subject)
#in函数用于检查一个对象是否为某个序列的成员,
#
而字符串唯一的成员或者元素是一个字符,实现'$$$' in subject功能,需要使用相关的字符串方法
【结果】
True
False
please input a user:foo
True
True
【代码】
#序列成员资格示例,检查用户和PIN码database = [
[
'albert','1234'],
[
'dllbert','4242'],
[
'smith','7542'],
[
'jones','9843']
]
username =
input("user
name:")
pin =
input("PIN
code:")
if([username,pin] in database):
print("Access granted")
【结果】
user name:albert
PIN code:1234
Access granted
2.2.6长度、最小值和最大值
【代码】
#内建函数len,max,min非常有用。len函数返回序列中元素的个数,min,max分别返回序列中最小和最大的元素numbers = [100,34,678]
print(len(numbers))
print(max(numbers))
print(min(numbers))
【结果】
3
678
34
2.3列表:Python的“苦力”
2.3.1 list函数
#本节讨论列表不同于元组和字符串的地方 ---列表是可变的,并且列表有很多有用的、专门的方法
【代码】
#字符串创建列表print(list('Hello'))
#注:list函数适用于所有类型的序列,而不只是字符串
【结果】
['H', 'e', 'l', 'l', 'o']
2.3.2 基本的列表操作
列表可以使用所有适用于序列的标准操作,例如索引、分片、连接和乘法。有趣的是,列表是可以修改的。本节会介绍:元素赋值、元素删除、分片赋值以及列表方法(并不是所有列表方法都真正地改变列表)
1.改变列表,元素赋值
【代码】
x = [1,1,1]
x[
1] = 2
print(x)
【结果】
[1, 2, 1]
2.删除元素
【代码】
names = ['Alice','Beth','Cecil','Dee-Dee','Earl']
del(names[2]) #或者delnames[2]print(names)
#注:del函数还可以删除其他元素,例字典元素,甚至是其他变量的删除操作
【结果】
['Alice', 'Beth', 'Dee-Dee', 'Earl']
【代码】
#分片是一个非常强大的特性,分片赋值操作则更加现实它的强大name = list('Perl')
print('1',name)
name[
2:] = list('ar')
print('2',name)
#进行一次一个的赋值(可以使用与原序列不等长的序列将分片替换name = list('Perl')
name[
1:] = list('ython')
print('3',name)
#分片赋值语句在不替换任何元素的情况下插入元素numbers = [1,5]
numbers[
1:1] = [2,3,4]
print('4',numbers)
#注:这里只是替换了一个空的分片,实际操作是插入一个序列
#
通过分片赋值来删除元素也是可以的numbers = [1,2,3,4,5]
numbers[
1:4] = []
print('5',numbers)
【结果】
1 ['P', 'e', 'r', 'l']
2 ['P', 'e', 'a', 'r']
3 ['P', 'y', 't', 'h', 'o', 'n']
4 [1, 2, 3, 4, 5]
5 [1, 5]
2.3.3 列表方法
方法:与函数密切相关的概念,它是一个与某些对象有紧密联系的函数,对象可能是列表,数字,也可能是其他类型的对象,一般来说,方法可以这样进行调用:
对象.方法(参数)
除了对象被放置到方法名之前,并且两者之间用一个点号分隔,方法调用与函数调用很类似。列表提供了几个方法。
[if !supportLists]1. [endif]append
【代码】
#append方法用于在列表末尾追加新的对象lst = [1,2,3]
lst.append(
4)
print(lst)
#注:list是个內建函数,如果使用ilst作为变量名,就无法调用list函数了,
# append
方法和其他一些方法类似,只是在恰当位置修改原来的列表,
#
它并不是简单的返回一个修改过的新列表----而是直接修改原来的列表。
#
在某些情况下,这也会带来其他的麻烦。
【结果】
[1, 2, 3, 4]
[if !supportLists]2. [endif]count
【代码】
#count方法统计某个元素在列表中出现的次数lst = ['to','be','or','not','to','be']
print(lst.count('to'))
x = [[
1,2],1,1,[2,1,[1,2]]]
print(x.count(1))
print(x.count([1,2]))
【结果】
2
2
1
[if !supportLists]3. [endif]extend
【代码】
#extend方法可以在列表的末尾一次性追加另一个序列中的多个值。即可以使用新列表扩展原有的列表a = [1,2,3]
b = [
4,5,6]
a.extend(b)
print(a)
#注:看起来像是连接操作,区别主要在于:它修改了被扩展的序列,而原始的连接操作则会返回一个全新的列表。
#
可以使用分片赋值来实现相同的结果:a = [1,2,3]
b = [
4,5,6]
a[
len(a):] = b
print(a)
#这样做虽然可行,但代码的可读性不如extend方法
【结果】
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
[if !supportLists]4. [endif]index
【代码】
#index方法用于从列表中找出某个值第一个匹配项的索引位置knights = ['we','are','the','knights','who','ni']
print(knights.index('who'))
print(knights.index('herring'))
【结果】
4
Traceback (most recent call last):
File"D:/python_file/20180113/test.py", line 4, in
print(knights.index('herring'))
ValueError: 'herring' is not in list
[if !supportLists]5. [endif]insert
【代码】
#insert方法用于将对象插入到列表中numbers = [1,2,3,4,5,6,7]
numbers.insert(
3,'four')
print(numbers)
#注:与extend方法一样,insert方法的操作也可以用分片赋值来实现。(但可读性不如insert方法numbers =[1,2,3,4,5,6,7]
numbers[
3:3] = ['four']
print(numbers)
【结果】
[1, 2, 3, 'four', 4, 5, 6, 7]
[1, 2, 3, 'four', 4, 5, 6, 7]
[if !supportLists]6. [endif]pop
【代码】
#pop方法会移除列表中的一个元素(默认是最后一个),并且返回该元素的值x = [1,2,3]
print(x.pop())
print(x)
x.pop(
0)
print(x)
#注:pop方法是唯一一个既能修改列表又返回元素值(除了None)的列表方法。
# pop
方法可以实现一种常见的数据结构--栈。Python没有入栈方法,但可以使用append方法来代替。
# pop
方法和append方法的操作结果来代替。x = [1,2,3]
x.append(x.pop())
print(x)
【结果】
3
[1, 2]
[2]
[1, 2, 3]
[if !supportLists]7. [endif]remove
【代码】
#remove方法用于移除列表中某个值的一个匹配项:x = ['to','be','or','not','to','be']
x.remove(
'be')
print(x)
x.remove(
'bee')
#注remove方法改变了列表,但是没有返回值
【结果】
['to', 'or', 'not', 'to', 'be']
Traceback (most recent call last):
File"D:/python_file/20180113/test.py", line 5, in
x.remove('bee')
ValueError: list.remove(x): x not in list
[if !supportLists]8. [endif]reverse
【代码】
#reverse方法将列表中的元素反向存放x = [1,2,3]
x.reverse()
print(x)
#注:该方法也改变了列表但也不返回值(就像remove和sort),如果需要对一个序列进行反向迭代,
#
那么可以使用reversed函数,这个函数不返回一个列表,而是返回一个迭代器(iterator)对象,
#
尽管这样,使用list函数把返回的对象转换成列表也是可行的x = [1,2,3]
lst =
list(reversed(x))
print(lst)
【结果】
[3, 2, 1]
[3, 2, 1]
[if !supportLists]9. [endif]sort
【代码】
#从python2.3开始,sort方法使用了固定的排序算法
#sort
方法用于在原位置对列表进行排序。意味着改变原来的列表,从而让其中的元素按一定的顺序排列,而不是返回一个排好序的副本x = [4,6,1,7,9]
x.sort()
print(x)
#注:sort方法只会返回None。
#
比如我们要实现一个功能:用户需要一个排好序的列表副本,同时又保留原有列表不变的操作。x = [4,6,2,1,7,9]
y = x[:]
y.sort()
print(x)
print(y)
#注:如果想把一些元素按相反的顺序排列,可以先使用sort,再使用reverse方法。或者也可以使用reverse参数
【结果】
[1, 4, 6, 7, 9]
[4, 6, 2, 1, 7, 9]
[1, 2, 4, 6, 7, 9]
[if !supportLists]10.[endif] 高级排序
………………………………
注:需要两次对列表调用sort方法,如果打算通过x.sort().reverse()来实现,会发现行不通,因为x.sort()返回的是None,当然,sorted(x).reverse()是正确的做法。
sort方法有另外两个可选的参数 ---key和reverse。如果要使用它们,就要通过名字来指定(关键字参数)。参数key与参数cmp类似—必须提供一个在排序过程中使用的函数。然而,该函数并不是直接用来确定对象的大小,而是为每一个元素创建一个键,然后所有元素根据键来排序。因此,如果要根据元素的长度进行排序,那么可以使用len作为参数。另一个关键字reverse是简单的布尔值,用来指明列表是否要进行反向排序。
【代码】
#如果希望元素能够按特定的方式进行排序(而不是sort函数默认的方式)。
#
那么可以使用compare(x,y)的形式自定义比较函数。compare(x,y)函数会在x < y是返回负数,
#
在x > y时返回正数,x = y则返回0x = ['aardvark','abalone','acme','add','aerate']
x.sort(
key=len)
print(x)
numbers = [
5,2,9,7]
numbers.sort(
reverse=True)
print(numbers)
【结果】
['add', 'acme', 'aerate', 'abalone', 'aardvark']
[9, 7, 5, 2]
2.4元组:不可变序列
【代码】
#元组和列表一样,也是一种序列。唯一不同的是元组不能修改(字符串也是如此)。创建元组:用逗号分隔一些值a = 1,2,3
b = (1,2,3)
c = ()
d = (
1) #只添加原括号是没用的,(1)和1是完全一样的。d2 = 1, #实现包含一个值的元组,有点特殊(必须加一个逗号),一个逗号就能彻底改变表达式的值print(a)
print(b)
print(c)
print(d)
print(d2)
【结果】
(1, 2, 3)
(1, 2, 3)
()
1
(1,)
2.4.1 tuple函数
tupel的英文释义为:元组
【代码】
#tuple函数的功能和list类似,以一个序列作为参数并把它转化为元组。tu1 = tuple([1,2,3])
tu2 =
tuple('abc')
tu3 =
tuple((1,2,3)) #如果参数本身是元组,则函数原样返回print(tu1)
print(tu2)
print(tu3)
【结果】
(1, 2, 3)
('a', 'b', 'c')
(1, 2, 3)
2.4.2 基本元组操作
【代码】
#元组其实不复杂--除了创建和访问元组外,没有太多其他操作,可以参照其他类型的序列来实现x = 1,2,3
print(x[1])
print(x[0:2])
#注:元组的分片还是元组,就像列表的分片还是列表一样
【结果】
2
(1, 2)
2.4.3 使用元组的意义
有两个原因,元组是不能被列表代替的
[if !supportLists]① [endif]元组可以在映射(和集合的成员)中当做键使用,而列表不行
元组作为很多內建函数和方法的返回值存在,所以必须对元组进行处理。只要不尝试修改元组,那么“处理”元组在绝大多数情况下就是把它当做列表来进行操作(除非使用一些元组没有的方法,例如index和count)