第四章 列表

列表和元组可以包含多个值,这样编写程序来处理大量数据就变得容易。而且列表本身又可以包含其他列表,所以可以用它们将数据安排成层次结构。

 

列表定义:"列表"是一个值,它包含多个字构成的序列。术语"列表值"指的是列表本身(它作为一个值,可以保存在变量中,或传递给函数,像其他数据类型一样)

组成部分:左方括号开始,右方括号结束,即[],列表中的值也称为“表项”,表项用逗号分隔,如[1,2,3,4,5]

 

用下标取得列表中的单个值

列表中的表项是依次从左到右,下标从0开始,取出列表中的表项:

>>>spam = [[1,2],1,'cat','dog']
>>>spam[0]  # 下标只能是整数,不能是浮点数,但是也可以为负数,表示从右向左开始依次类推。
[1,2]

>>>spam[1]
1

>>>spam[2]
 'cat'

>>>spam[3]
'dog'

>>>spam[-1]
'dog'

>>>spam[-2]
'cat'

上面的例子,如果想要取出列表中的列表的中的值,可以通过多重下标来访问:

>>>spam = [[1,2],1,'cat','dog']

>>>spam[0][0]
1

>>>spam[0][1]
2

 

用切片取得子列表

就像下标可以从列表中取得单个值一样,"切片"可以从列表中取得多个值,生成一个新的列表

  • 在一个切片中,第一个数是切片开始处的下标(包括它),第二个数是切片结束的下标(但不包括它)。
>>>spam[1:2]
[1]

>>>spam[0:2]
[[1,2],1]
  • 快捷方法,也可以省略切片中":"两边的一个或两个下标。
>>>spam[1:]
[1,'cat','dog']

>>>spam[:2]
[[1,2],1]

>>>spam[:]
[[1,2],1,'cat','dog']

 

len()取得列表的长度

len()函数将返回传递给它的列表中值的个数:

>>>spam = [[1,2],1,'cat','dog']
>>>len(spam)
4

常和循环一起使用:

循环是针对一个列表或类似列表中的每个值,重复地执行代码块。

spam = ['elephant',1,'cat','dog']
for i in range(len(spam)):
    print('index'+ str(i) + 'item:' + spam[i])
#输出
index 0 item:elephant
index 1 item:1
index 2 item:cat
index 3 item:dog

# 在前面的循环中使用range(len(spam))很方便,这是因为,循环中的代码可以访问下标(通过变量i),以及下标处的值(通过spam(i)。最妙的是range(len(spam))将迭代spam的所有下标,无论它包含多少表项。

 

列表的连接和复制(和字符串的连接类似)

操作符+:可以连接两个列表,得到一个新的列表

操作符*:可以用于1个列表和1个整数,实现列表的复制

 

列表的增、删、改、查

增加

  • 使用append()添加表项到列表末尾
>>>spam = [[1,2],1,'cat','dog']
>>>spam.append('elephant')
>>>spam
[[1,2],1,'cat','dog','elephant']
  • 使用insert()方法根据下标插入表项,第一个参数是新值的下标,第二个参数是要插入的新值
>>>spam = [[1,2],1,'cat','dog']
>>>spam.insert(1,'elephant')
>>>spam
[[1,2],'elephant',1,'cat','dog']

注意:append()和insert()返回值都是None.

 

删除

  • del语句根据下标删除列表中的值
>>>spam = [[1,2],1,'cat','dog']
>>>del spam[1]
>>>spam
[[1,2],'cat','dog']
  •  使用remove()方法从列表中删除值
>>>spam = [[1,2],1,'cat','dog']
>>>spam.remove('cat')  # 如果列表中存在重复的值,就删除它第一次出现值
>>>spam
[[1,2],1,'dog']

 

修改

通过列表的下标,来改变下标处的值

>>>spam = [[1,2],1,'cat','dog']
>>>spam[1] = 'philippines'
>>>spam
[[1,2],'philippines','cat','dog']

 

查看

  • 通过下标进行查看
>>>spam = [[1,2],1,'cat','dog']
>>>spam[1]
1
  •  知道列表中表项的情况下,通过index()查询下标
>>>spam = [[1,2,1,'cat','dog'] #如果列表中存在重复的值,就返回它第一次出现的下标
>>>spam.index(1)
0

 

sort()方法将列表中的值排序

>>>spam = [2,5,7,9,1,0]
>>> spam.sort()
>>>spam
[0,1,2,5,7,9]

 
>>>spam = ['a','q','A','E']
>>>spam.sort()
>>>spam
#输出
['A', 'E', 'a', 'q']

也可以指定reverse关键字参数为True,让sort()按逆序排序。

spam = ['a','q','A','E']
spam.sort(reverse=True)
print(spam)
#输出
['q', 'a', 'E', 'A']

#注意:
sort()返回值也是None.
sort()方法对字符串排序时,使用"ASCII"字符排序,小写在前大写在后

 

in和not in操作符

利用in 和not in操作符,可以确定一个值是否在列表中。

>>>'dick' in ['dick','jacky','maria']
True

>>>spam =  ['dick','jacky','maria']
>>> 'sophie' in spam
False

>>> 'sophie' not in spam
True

 

多重赋值技巧

多重赋值技巧是一种快捷方式,让你在一行代码中,用列表中的值为多个变量赋值。所以不必像这样:

>>>user_database = ['dick,123123,0]
>>>username = user_database[0]
>>>password = user_database[1]
>>>history = user_database[2]
而是输入以下代码:
>>>user_database = ['dick,123123,0]
>>>username,password,history = user_database #变量的数目和列表的长度必须严格相等,否则报错。

 

增强的赋值操作

 

>>>spam = 42
>>>spam +=1
>>>spam
43

 

 

作为一种快捷方式,可以使用增强的赋值操作符+=来完成同样的事:

>>>spam = 'hello'
>>>spam += 'world'
>>>spam
"hello world"


>>>bacon = ['zophie']
>>>bacon+=3
>>>bacon
 ['zophie','zophie','zophie']

 

和字符串的异同

字符串可以理解为是单个字符的列表

相同点:

对列表的许多操作,也可以作用于字符串:

按下标取值

切片

用于for循环

len()

in 和not in操作符

 

可变和不可变数据类型

列表是可变的数据类型,它的值可以添加、删除或改变,

字符串是不可变的,它不能被更改:改变字符串的正确方式只能使用切片和连接,构造一个新的字符串

 

尽管列表值是可变的,但下面代码中的第二行并没有修改列表spam:

>>>spam = [1,2,3]
>>>spam = [4,5,6]
>>>spam
[4,5,6]

这里的spam中的列表值并没有改变,而是整个新的列表值([4,5,6]),覆写了老的列表值。如果确实希望修改原来的列表,那么:

>>>spam = [1,2,3]
>>>del spam[2]
>>>del spam[1]
>>>del spam[0]
>>>spam.append(4)
>>>spam.append(5)
>>>spam.append(6)
>>>spam
[4,5,6]
#改变一个可变数据类型的值(就像上面例子中del语句和append()方法所做的事)当场改变了该值,因为该变量的值没有被一个新的列表值取代。

这个例子中,spam最后的列表值与它开始的列表值是一样的。只是这个列表被改变了,而不是被覆写。

 

接下来,我们来看看元组数据类型,他是列表数据类型的不可变形式

 

元组数据类型

元组和列表只有2点区别:1.元组使用(),2.元组不可变

如果元组中只有一个值,你可以在括号内该值后面跟上一个逗号,表明它是一个元组。

>>>type(('hello',))
<class 'tuple'>

>>>type(('hello'))
<class 'str'>

如果你需要一个永远不改变的序列,就用元组。

 

元组与列表之间的转换

使用list()和tuple()函数来转换类型

>>>tuple([1,2,3])
>>>(1,2,3)

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

如果需要元组值得一个可变版本,将元组转换成列表:

>>>list((1,2,3))
[1,2,3]

 

引用

变量保存字符串和整数值:

>>>spam =42
>>>cheese = spam
>>> spam = 100
>>> spam
100

>>> cheese
42

#你将42赋给spam变量,然后拷贝spam中的值,将它赋给变量chees。后面将spam值改变为100后,这不会影响cheese中的值。这是因为spam和cheese是不同的变量,保存了不同的值。

但是,
列表不是这样的。当你将列表赋给一个变量时,实际上是将列表的"引用"赋给了该变量。引用是一个值,指向某些数据。列表引用指向同一个列表的值

>>>spam = [1,2,3,4,5,6]
>>>cheese = spam
>>>cheese[1] = 'hello'
>>>spam
[1,'hello',3,4,5,6]

>>>cheese
[1,'hello',3,4,5,6]
#当创建列表spam时,你将对它的引用赋给了变量。但是下一行cheese只是将spam中的列表"引用"拷贝到cheese,而不是列表值本身。这意味着存储在spam和cheese中的值,现在指向了同一个列表。底下只有一个列表,因为列表本身实际从未复制。所以当你修改cheese变量的第一个元素时,也修改了spam指向的同一个列表。

 

总结:列表变量实际上没有包含列表,而是包含了对列表的“引用”(这些引用包含一些ID数字,Python在内部使用这些ID)

spam = [1,2,3,4,5,6] #保存了对列表的引用,而非实际列表

spam = cheese        #复制了引用,而非列表

所以,对于字符串和整数值或元组,变量就包含了字符串(str)或整数(int)或元组(tuple),Python变量就使用值本身。而在变量必须保存可变数据类型(列表或字典)的值时,Python就使用引用。

 

copy模块的copy()个deepcopy()函数

import copy

copy.copy():  #用来复制列表或字典这样的可变值,而不只是复制引用

copy.deepcopy():  #用来复制的列表中包含了列表,就使用这个函数,该函数将同时复制它们内部的列表

 

习题:

1.什么是[]?

答:列表是一个值,它由多个字符构成的序列

 

2.如何将'hello'赋给列表的第三个值,而列表保存在名为spam的变量中?(假定变量包含[2,4,6,8,10])

答:直接赋值即可,spam[2] = 'hello' 就将'hello'赋值给列表的第三个值

 

对接下来的3个问题,假定spam包含列表['a','b','c','d']

3.spam[int('3'*2)/11]求值为多少?

答:'a'

 

4.spam[-1]求值为多少?

答:'d'

 

5.spam[:2]求值为多少?

答:['a','b']

 

对接下来的3个问题。假定bacon包含列表[3.14,'cat',11'cat',True]

6.bacon.index('cat')求值为多少?

答:1

 

7.bacon.append(99)让bacon中的列表值变成什么样?

答:[3.14,'cat',11'cat',True,99]

 

8.bacon.remove('cat')让bacon中的列表值变成什么样?

答:[3.14,'cat',11,True]

 

9.列表链接和复制的操作符是什么?

答:列表连接:+,列表复制*

 

10.append()和insert()列表方法之间的区别是什么?

答:append()是将值插入到列表的最后,而insert()是将值插入任意的位置。

 

11.从列表中删除值有哪两种方法?

答:del和remove

 

12.请说出列表值和字符串的几点相似之处。

答:字符串是单个文本字符的列表,1.都可以使用下标进行取值,切片 2.都可以使用+/*操作符进行连接和复制 3.用于for循环/len(),in 和not in操作符

 

13.列表和元组之间的区别是什么?

答:列表中的值是可变的,元组是不可改变的

 

14.如果元组中只有一个整数值42,如何输入该元组?

答:(42,)

 

15.如何从列表值得到元组形式?如何从元组值得到列表形式?

答:使用list()方法和tuple()方法

 

16.“包含”列表的变量,实际上并未真正的直接包含列表。他们包含的是什么?

答:包含了对列表的引用,这些引用包含了同一块内存地址,并不是真正的列表

 

17.copy.copy()和copy.deepcopy()之间的区别是什么?

答:copy.copy()可以用来复制列表或字典这样的数据类型,而不是复制引用;而copy.deepcopy()是同时复制他们内部的列表

 

posted @ 2017-06-30 11:01  Mr.hu  阅读(484)  评论(0编辑  收藏  举报