导学

本节知识点

本节知识点

注:本节内容很重要,但是也很细很杂,所以我们不能只是照抄一遍,还要加强记忆,不要混淆。
在下面的整理中,也会尽量条理的进行记录,便于记忆和查阅。

目标和任务

目标、任务

3.1 序列

本节思维导图

思维导图

3.1.1 序列简介

  • 序列是一种包含多种数据的数据结构,这种数据结构按照顺序存储。python中常见的序列类型包含字符串、列表、元组
  • 不可变序列是指数据结构一旦建立,就不能修改其中的元素,字符串元组是不可变序列。
  • 可变序列:与上相反,其元素可以进行修改,列表字典集合是可变序列。
  • 正向递增序号,从0开始;反向递增序列,从**-1**开始。

递增图

示例

:对于可变序列,改变其中元素的值,其地址不会发送改变,

3.1.2 创建列表和元组

使用[item0,item1,item2…]创建列表
使用(item0,item1,item2…)创建元组

eg3.1.2-1


列表和元组之中的数据项可以相同也可以不同。

eg3.1.2-2

3.2 列表和元组的通用操作

这一小节介绍列表和元组的通用操作,也就是二者都可以使用的操作,后面再介绍二者的特有操作。

本节思维导图:

思维导图-3.2

通用操作1:索引查找和切片

通过索引访问元素

这一操作在前面已经介绍过,不再赘述。需要注意的是访问时的正向和反向起始值的区别。


slice切片

此内容很重要,也很灵活,要多多实践。
只要序列可以通过索引进行操作,就可以进行切片。包括:字符串、元组、列表、range等有序序列。

作用:通过索引获取序列中的某一段
语法格式 [start:end:step]

  • start:切片开始的索引,默认为0。
  • end:切片结束的索引,默认为序列长度。(不包含end)
  • step: 步长,默认为1。其正负表示切片方向。

示例

进行切片操作时,最重要的是判断对起始和结束的位置,同时结束位置是开区间,不取此值。
但是当结束位为空时,会根据步长决定是走到最后还是最前端。

通用操作2

操作1:查找和计数——>

  • list.index(x):x在列表中的第一次出现的位置,不存在抛出异常
  • list.count(x):x在列表中出现的次数,不存在返回0

index-eg

count-eg


操作2:最大值、最小值、长度——>

使用内置函数max(),min(),len()实现上三功能。
注:列表和元组的元素类型必须相同。

eg-3.2.2


操作3:加法、乘法、in运算——>

  • list1+list2:返回二者元素之和
  • list * n :对应的列表或者元组重复n遍
  • x in list1 :判断x是否在其中,True or False

加法

乘法

in运算


操作4:序列封包和解包——>

  • 序列封包:将多个值赋给一个变量时,python会把这些值封装为一个元组。
  • 序列解包:将序列直接赋给多个变量时,序列中的元素一次赋值。

示例

3.3 列表的操作

下面来介绍一下列表的特有操作

思维导图如下:
思维导图-3.3

3.3.1 学前准备:dir()函数

dir()函数可以查看对象内的所有的属性和方法

eg-3.3.1

在一系列方法里我们要重点关注不带下划线的部分。

3.3.2 常用操作汇总

以下操作会改变原列表数据,所以元组不可以使用。

操作1:list()创建列表

使用内置函数list()创建列表

eg-1


操作2:增加元素

  • append(x):在列表尾部追加元素。(注:此方法可以接受单个值,也可以接收元组或列表,但是此时,元组和列表是作为一个整体追加的,这样就形成了嵌套。)
  • insert(d,x):在列表的指定位置插入元素
  • extend(x):将一个列表追加到列表尾部,不是作为一个整体。

eg-2

:使用extend()追加元素是,必须是可迭代对象(for in可遍历:列表、字符串、元组、字典)


操作3:删除元素

  • del():根据索引删除列表的一个元素或一段区间的元素
  • remove():根据元素本身删除列表的某一个元素
  • clear():清空列表

eg-3
这里注意:del()的使用与其他不同,是在列表前面

下面是一个例子

我们发现,第二个方法无法实现。这是因为我们删除的x与 for in的x是一个列表,而这个列表是变化的。


操作4:置逆和排序

  • reverse():将列表元素置逆,返回一个迭代器。
  • sort():将列表元素排序(默认从小到大。使用参数reverse=True可以反向排序)

eg-4-1

eg-4-2

:内置函数sorted()也可进行排序,其余sort()的区别如下

  1. list.sort()为列表定义的,而sorted函数可以接受任何可迭代对象。
  2. list.sort()会直接修改原列表,而sorted会产生一个新的排序列表。


可见,使用sorted()不会改变原列表,而是生成一个新的列表。


操作5:弹出元素

  • pop():将列表作为栈,实现出栈操作。入栈操作使用append()。
  • pop(0):将列表当做队列,实现出队操作。入队使用append()。

eg-5

3.3.3 深拷贝和浅拷贝

  • shalldow copy 浅拷贝
  • deepcopy 深拷贝

shalldow copy 浅拷贝

list.copy()copy.copy(list)都是浅拷贝

浅拷贝

可见,浅拷贝后的两个列表是存在联系的,具体是拷贝过后的list2如果改变其可变元素(如列表),会使得list1也一起发生变化。

deepcopy 深拷贝

copy.deepcopy(list)是深拷贝的实现方法。

深拷贝

深拷贝的两个列表无关联。

list1=list2

等号

经过等号连接的两个列表是完全关联的,一个变化另一个也会变化。

三种拷贝方式的原因

python对数据的存储方式的不同

究其原因,在于拷贝后的列表,其各个元素的存储空间是否与原列表的存储空间相同。

  • 浅拷贝:可变元素的存储空间与原列表一致,其他元素有新的存储空间。
  • 深拷贝:拷贝后的列表其元素都有了新的存储空间。
  • 等号:拷贝后的列表其元素与原列表元素存储空间一致。

验证

3.4 元组操作

思维导图:
思维导图-3.4

相对于列表,元组在创建之后不可改变。

操作1:元组的创建

使用tuple()内置函数或者(item,)进行创建

注:使用小括号进行创建时,如果只有一个元素,需要在其后加上逗号。


操作2:元组和列表的转换(内置函数)

  • list()将元组转换为列表
  • tuple()将列表转换为元组

eg2

通过这种方法可以实现元组的变化。

3.5 字典

列表和元组都是一个有序序列,可以通过索引访问元素。但是如果我们不知道索引,就需要进行遍历查找元素。这是一个耗时的过程,所以引入字典。
假设数据本身具有唯一性,这时可以通过字典的方式进行存储,实现快速查找

本节思维导图:
思维导图-3.5

3.5.1 字典的创建和访问

操作1:字典的创建

  1. 通过{key1:value,key2:value...}等键值对的方式创建
  • 可以是python中任意不可变的元素,包括:实数复数字符串元组等,但不可以是
  • 列表集合字典可变元素
  • 通过键获取值的位置。
  • 键是唯一的,不可重复;值不可以重复

eg-3.5.1-1

  1. 通过内置函数dict()创建字典

eg-3.5.1-2

  1. 以关键参数的形式创建字典

eg-3.5.1-3

  1. fromkeys()方法

语法格式dict.fromkeys(seq[,value])
作用:用于创建一个新的字典,

  • seq – 字典键值列表
  • value – 可选参数, 设置键序列(seq)的值

例子:


操作2:访问元素

通过dict[键] 访问对应的值。
注:字典是无序的,不可以通过索引进行访问。

eg-3.5.1-4

使用sorted()进行排序

对字典进行排序,会返回一个列表,将其键进行排序。原字典不会改变。

3.5.2 字典的增删改

操作1: 增加字典元素

d[key]=value:将key对应的值修改为value,不存在则增加对应键值对 .

eg-3.5.2-2


操作2:删除元素(后置)

  • del dict[key]:通过键来删除元素,键不存在会报错.
  • popitem()返回并删除字典的最后一个键值对.,封装为一个元组(如下图)
  • pop(key):key存在就删除,并返回value值.

eg1

eg2

eg3

:del是内置函数,而其余两个为方法,后置且使用小括号.


get()和item()方法

  • get():用来返回指定对应的值,不存在时返回None.
  • items():用于返回键值对,使用元组封装。可以使用这个方法使用for in进行遍历

eg-3.5.2-3


keys()方法和values()方法

  • keys():返回字典的键,以列表的形式。
  • values():返回字典的值,以列表的形式。

eg-3.5.2-4


updata方法

语法格式d1.update(d2)
作用:会把d2放到d1中,重复的元素会以d2为主进行覆盖。


字典长度和字典检索

  • len(dict):返回字典中键的数目
  • key in dict :某键是否存在,True or False

eg-3.5.2-5

eg-3.5.2-6


字典的应用:计数器

思路:利用for in 循环进行遍历列表,而后通过dict[key]+=1的形式进行计数。

1
2
3
4
5
6
7
8
9
10
itemList = [1,3,3,5,1,2,1,5,9,5,5]

counter = {}
for item in itemList:
if item in counter:
counter[item]+=1
else:
counter[item]=1
print(counter)

3.6 容器类

主要介绍collections容器类,作为上数据类型的替代选择

思维导图-3.6

会在模块扩展进行介绍.

3.7 比较各个方法的时间效率

比较list的append()和insert()的时间效率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from time import time
def time_aver1(n):
list1 = []
start = time()
for i in range(n):
list1.append(None)
end = time()
return (end-start)/n

def main():
time_append = time_aver1(10000)
print(time_append)


if __name__=='__main__':
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from time import time

def time_aver2(n):
list1 = []
start = time()
for i in range(n):
list1.insert(5,None)
end = time()
return (end-start)/n

def main():

time_insert = time_aver2(10000)

print(time_insert)

if __name__=='__main__':
main()

通过比较可以看出,append()的时间效率高于insert()
原因:列表并不是链表,而是一种动态的数组。在进行插入时,append()会直接在列表最后插入元素,没有之后元素的移动;而insert()在插入时会查询插入的位置,同时将其后的元素后移,导致时间效率较低。

我们可以使用insert()在队尾插入,发现其时间效率与append()差不多。

使用列表实现栈、对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def Stack_push(x,list1):
list1.append(x)
return list1

def Stack_pop(list1):
list1.pop()
return list1

def enQueue(x,list1):
list1.append(x)
return list1

def deQueue(list1):
list1.pop(0)
return list1

def main():
stack1 = [1,2,3,4]
print("入栈出栈操作:")
print(Stack_push(5,stack1))
print(Stack_pop(stack1))

Queue = [1,2,3,4]
print("入队出队操作:")
print(enQueue(5,Queue))
print(deQueue(Queue))

if __name__ == '__main__':
main()

3.8 其他数据结构

灵活使用append()与popleft()

双端队列

堆


3.9 本章总结

对上述几种数据类型的操作方法

  • 对于方法,一般是直接在原类型本体上操作的,不会返回一个新的类型。例如列表进行append,前后列表的元素不同但是地址一致。
  • 而对于sorted()这样的函数,会返回一个新的数据类型。

对可切片、可迭代、可变的理解

  • 可不可以切片要看是否可以索引,即是否有下标。string、tuple、list、range是可切片,dict、set不可。
  • 可不可以迭代要看是否可以for in 遍历。string、tuple、list、dict、set等可以进行迭代。但不是所有的可迭代对象都是迭代器。
  • 可不可以变化强记即可,string、tuple是不可变,其余是可变。

本章错误汇总

1、一个键不可以对应多个值信息。

2、zip()函数的使用
2

3、dict.get()的使用:注意参数

4、杨辉三角的打印

1
2
3
4
5
6
7
8
list1 = [1]
for i in range(num):
for j in list1:
print("%-d"%j,end='\t')
list1.append(0)
print("")
list1 = [list1[k]+list1[k-1] for k in range(i+2)]

关键在于每一层列表的生成,这里使用列表生成式