序列按存储元素类型是否一致可分为:扁平序列、容器序列。

扁平序列:string(字符串)、array.array(数组)、memoryview(内存视图)、bytes(字节串)、bytearray(字节数组)

扁平序列中所有元素都为同类型数据。

容器序列:list(列表)、tuple(元组)、collection.deque(双向队列)

容器序列则可以存储不同类型的数据,但容器序列实际存储的是个元素的引用。支持元素嵌套

序列按是否更改又能分为:可变和不可变序列。

可变序列:list、array.array、bytearray、colloction.deque、memoryview

不可变序列:tuple、string、bytes

字典和集合严格意义上说并不属于序列。序列即为一系列数据元素有秩序的组合在一起,构成一个整体,是一种组织数据的模型。

python中有序序列如list、tuple、str和range等都支持双向索引

正向索引:从0开始

逆向索引:-1代表倒数第一个元素,-2代表代数第二个元素,以此类推

列表列表为python内置的可变序列数据结构之一,包含若干==有序连续==的内存空间。

当列表增加或删除元素时,列表对象会自动进行内存的扩展或收缩,以保证元素之间没有缝隙。

由于在列表中间插入或删除元素时会涉及大量元素的移动,效率较低,因此尽量从尾部增删元素。

==*同一列表中的元素的数据类型可以各不相同==

因为基于值的内存管理机制,列表中元素并不直接存储值,而是存储值的引用(或者说对象的引用)。

列表的创建list()内置函数

操作符,各元素之间用逗号隔开

列表的基本操作原地操作(通常都是list对象自带的行为操作,del命令删除指定位置元素)

函数

功能

lst.append(x)

在列表lst末尾增加元素X

lst.extend(lst2)

在列表lst与lst2合并,==与lst+=lst2效果一样且都是原地操作.

但lst=lst+lst2则会改变lst的id值,即lst+lst2返回一个新的列表对象==

lst.insert(index,x)

在列表lst指定的index位置插入元素x

lst.remove(x)

删除列表lst中元素x

lst.pop([index])

返回并删除列表lst指定index位置的元素,

默认为列表尾部元素

lst.clear()

删除列表lst中所有元素,但保留列表对象,

即返回空列表

lst.index(X)

返回列表lst中第一个为X的元素的下标

lst.count(x)

返回指定元素X在列表lst中出现的次数

lst.reverse()

将列表lst逆序,lst发生变化(原地操作)

而内置函数reversed(lst)为非原地操作,原lst不变,返回一个新列表

lst.sort(key=None,reverse=False)

将lst排序(原地操作)

lst.copy()

返回列表lst的==浅复制==

浅复制&深复制

我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。

浅复制并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。这就和我们寻常意义上的复制有所不同了。

对于简单的 object,用 shallow copy 和 deep copy 没区别

复杂的 object,如 list 中套着 list 的情况,shallow copy中的子list,并未从原object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。

理解原子对象和容器对象

非原地操作(Python内置函数,运算符+、*等)

>>> x=list(range(10))
>>> y=x #x,y指向同一个对象,由id(x),id(y)可以看出
>>> y
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> id(x)
2568897570056
>>> id(y)
2568897570056
>>> import random
>>> random.shuffle(x) #随即打乱
>>> x
[3, 7, 1, 6, 8, 2, 0, 9, 4, 5]
>>> x is y
True
>>> y
[3, 7, 1, 6, 8, 2, 0, 9, 4, 5]
>>> x.pop() #原地操作
5
>>> id(x)
2568897570056
>>> x.append(258) #原地操作
>>> x
[3, 7, 1, 6, 8, 2, 0, 9, 4, 258]
>>> y
[3, 7, 1, 6, 8, 2, 0, 9, 4, 258]
>>> id(x)
2568897570056
>>> x.extend([15,51]) #原地操作
>>> y
[3, 7, 1, 6, 8, 2, 0, 9, 4, 258, 15, 51]
>>> id(y)
2568897570056
>>> x.insert(0,'insert') #原地操作
>>> x
['insert', 3, 7, 1, 6, 8, 2, 0, 9, 4, 258, 15, 51]
>>> x.remove(7) #原地操作
>>> x
['insert', 3, 1, 6, 8, 2, 0, 9, 4, 258, 15, 51]
>>> x.reverse() #list对象本身自带逆序函数,原地操作
>>> x
[51, 15, 258, 4, 9, 0, 2, 8, 6, 1, 3, 'insert']
>>> x.pop()
'insert'
>>> x
[51, 15, 258, 4, 9, 0, 2, 8, 6, 1, 3]
>>> x.sort() #原地操作
>>> x
[0, 1, 2, 3, 4, 6, 8, 9, 15, 51, 258]
>>> reversed(x) #内置函数进行逆序,非原地操作,返回新的对象。x不变
>>> x
[0, 1, 2, 3, 4, 6, 8, 9, 15, 51, 258]
>>> sorted(x,reverse=True) #非原地操作,产生新的列表
[258, 51, 15, 9, 8, 6, 4, 3, 2, 1, 0]
>>> x
[0, 1, 2, 3, 4, 6, 8, 9, 15, 51, 258]
>>> x=x+[1,2] #非原地操作(*)
>>> id(x)
2569288051976
>>> id(y)
2568897570056
>>> y
[0, 1, 2, 3, 4, 6, 8, 9, 15, 51, 258]
>>> y+=[1,2] #原地操作(与上一语句(*)对比)
>>> y
[0, 1, 2, 3, 4, 6, 8, 9, 15, 51, 258, 1, 2]
>>> id(y)
2568897570056

python中内置函数map(),filter(),reduce()等函数是==python函数式编程==的重要体现

(reduce()函数在python3中不是内置函数,而是在functools库中)

注:下表中的lst不一定是列表,其他可迭代对象均可

函数 | 功能

— | —

map.(func,lst) | 返回列表lst中每个元素经过函数func映射后的结果列表,

这里的func也可以是lambda函数

filter(func,lst) | 将一个单参数函数作用到序列lst上,并返回该序列中使得该函数

返回值为True的那些元素组成的filter对象,如果指定函数为None,

则返回序列中等价于True的元素所组成的filter对象

reduce(func,lst) | 将一个两参数函数以累积方式从左到右依次作用到序列lst上

zip(seq1[,sep2[,sep3…]]) | 返回元素为元组的新列表

enumerate(seq) | 枚举列表元素,返回enumerate对象

>>> a=list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b=list(map(lambda x :chr(x+ord('A')),a))
>>> b
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
>>> list(enumerate(b))
[(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E'), (5, 'F'), (6, 'G'), (7, 'H'), (8, 'I'), (9, 'J')]
>>> list(filter(lambda x:x>6,a))
[7, 8, 9]
[x>6 for x in a ]
[False, False, False, False, False, False, False, True, True, True]
>>> from functools import reduce
>>> reduce(lambda i,j:i+j ,a)
45

切片通过切片获取列表部分元素

可以通过切片实现删除、更改、增加元素

通过切片进行浅复制

列表推导式[表达式或函数式 for 变量 in 可迭代对象]

列表推导式结合if语句过滤元素

列表推导式实现多重循环

列表推导式实现矩阵转置

列表推导式内使用函数或复杂表达式

array.array

简介

array数组类型和C语言中的数组很类似,可以指定数组中存储元素的类型。特点是速度快,可以通过实例方法存储和读取二进制文件。

实例

collection.deque

简介

列表可以通过pop()方法和append()方法来实现“先进先出”的队列属性,但由于频繁移动元素导致效率不高。deque类型专门对入队出队进行了优化。

实例

元组及具名元组

元组

元组基本知识元组为不可变序列,支持切片操作,但只能通过切片来访问元组中的元素。可以将元组看成‘常量列表’。

当元组中的元素包含可变序列(如列表)时,情况变得不一样。

python对元组内部做了优化,其访问和处理速度比列表更快。而且由于其不可改变的特点通常用来==函数调用时进行参数传递==

>>> a= (1,2,3)
>>> a
(1, 2, 3)
>>> type(a)
>>> b=a[:]
>>> b
(1, 2, 3)
>>> c=(3) #c=3等价,创建含一个元素的元组如d
>>> c
3
>>> type(c)
>>> d=(3,)
>>> d
(3,)
>>> type(d)
>>> e=()
>>> e
()
>>> f=tuple()
>>> f
()
>>> g=tuple([1,2,34,5])
>>> g
(1, 2, 34, 5)

生成器推导式格式:(表达式 for 变量 in 序列或迭代对象)

生成器推导式的结果为一个生成器对象

==生成器对象==:

可以使用工厂函数list(),tuple()将其转化为列表或元组,也可以通过生成器对象本身的next方法或内置函数next()进行遍历,也可将其直接当做迭代器对象使用。但无论如何遍历或使用,当所有元素遍历完后,需要重新创建生成器对象才能重新访问其中的元素。生成器对象的优点是节省内存空间

包含yield关键字的函数可以用来创建可迭代的生成器对象

注意事项尽量不要把可变序列作为元组的元素

增量赋值不是 原子操作,对于可变序列,+=运算符调用–iadd–() 特殊方法,就地操作。而不可变序列则没有–add–(),是通过–add–()方法实现的,此时会创建一个新的对象,完成操作后与原变量关联。

具名元组

collection.namedtuple()是一个工厂函数,用来构建带字段名的元组和带名字的类。

实例

序列解包对多个变量同时赋值

同时遍历多个序列

在实参前加*号可以实现序列解包并在函数调用时进行参数传递

元组拆包常常用来传递函数参数。