Python科学计算第二章 Python序列

概述

列表:可变,有序

元组:不可变,有序

字典:可变,无序 # Python3.7之后变为有序

集合:可变,无序

字符串:不可变,有序

range:不可变,有序

注意:zip, filter, enumerate, map不是序列而是迭代器,因此返回的对象不支持进行len,切片的操作(但可以正常进行max、sum操作,以及使用 sorted 函数排序(这些操作会消耗迭代器))


序列操作常用内置函数

1. all, any

all(序列):所有元素全True则返回True

any(序列):有元素True则返回True

2. len, max, min, sum

len(序列):返回序列中元素的个数

其余见第一章常用内置函数

3. zip, enumerate等

见第一章常用内置函数


列表 list

1. 列表创建

  1. lst = list(序列)
  2. lst = [元素1, 元素2, 元素3, ...]

2. + 列表连接与 * 列表扩展

+ 表示列表连接

例如:lst = lst1 + lst2

* 表示列表扩展

例如:lst = [1, 2, 3] * 3 # 结果为[1, 2, 3, 1, 2, 3]

注意乘号是复制列表的引用,不是直接复制原列表的值,例如:

x = [[None] * 2] * 3 # [[None, None], [None, None], [None, None]] x[0][0] = 5 # [[5, None], [5, None], [5, None]]

3. 增删查改、逆序、排序

# 增 lst.append(元素) # 尾部追加元素 lst.extend(序列) # 尾部追加序列中所有元素 # 删 lst.remove(x) # 删除第一个值为x的元素,x不存在抛ValueError del lst[idx] # 使用del命令删除下标idx的元素 lst.pop(idx=-1) # 删除下标为idx的元素,默认为-1即最后一个,并返回该元素的值,索引超限抛IndexError # 查 lst.index(x) # 返回第一个值为x的元素的下标,x不存在抛ValueError lst[idx] # 返回下标idx元素,索引超限抛IndexError lst.count(x) # 返回x出现次数,未出现则为0 x in lst # in关键字查看x是否在列表中,不在False,在True # 改 lst.insert(idx, x) # 在下标idx插入x,插入后下标idx位置为x lst[idx] = newx # 下标idx元素修改为newx # 逆序 lst.reverse() # 原地操作,无返回值 # 排序 lst.sort(key=None, reverse=False) # 原地操作,无返回值,根据key排序,reverse为True则逆序 lst = sorted(lst, key=None) # 有返回值,使用内置函数对列表排序

删除时的错误删法:

因迭代器会不断+1,而删除元素后后方元素会递补,导致迭代器和部分元素错过

正确删法:正确删法:

应该从后往前删

4. 切片方法

lst[起始:终止:步长]

左闭右开[起始,终止)

切片不会因下标越界抛出异常,会在列表尾部截断或返回空列表

在区间[起始,终止)按照步长切,要想切出元素则必须

  1. 起始 < 终止 且 步长为正
  2. 起始 > 终止 且 步长为负

起始位和终止位默认值(根据步长情况)

  1. 步长为正数或不填:起始默认0,终止默认len(lst)

  2. 步长为负数:起始默认-1,终止默认-len(lst)-1

若切片起始、终止均不填,只填了步长,形如lst[::步长],则切片情况如下(根据步长情况)

  1. 步长为空:-> 为lst[::],等价于lst[:],步长为1

  2. 步长为正数:-> 从 [0, len(lst)) 按步长切

  3. 步长为负数:-> 从[-1, -len(lst)-1) 按步长切(此时为倒着切)

做题时先把负下标转化成正下标:负下标 + len(lst) = 正下标

5. 用切片原地操作修改列表

# 增 lst[idx:idx] = lst2 # 在idx处插入lst2中所有元素 # 删 lst[切片] = [] # 删除被切到的值 del lst[切片] # 删除切片部分 # 改 lst[切片(连续,步长为1省略)] = lst2 # 将连续切片切到的部分改为lst2中元素 lst[切片(不连续)] = 和切到的部分元素个数一样多的列表 # 切片不连续两侧元素必须一样多,被切到的值一一对应改成右边列表中元素

6. 切片只复制引用

如果原列表中只包含整数、实数、复数等基本类型或元组、字符串等不可变类型的数据,修改其中一个切片不会影响原列表和其它切片

如果有列表等可变序列,对它们进行修改则会影响原列表和其它切片

仅含整数与含整数、列表的列表的切片对比

根据引用对被引用的列表进行了操作

但指针的朝向不变


列表推导式

元组、字典、集合也有类似的推导式

1. 创建

lst = [表达式 for item in 可迭代对象]

2. 嵌套

列表推导式嵌套从左往右嵌套

# 假设有lstt列表,为列表的列表如[[1, 2, 3], [4, 5, 6], [7, 8, 9]] result = [a2 * a2 for a1 in lstt for a2 in a1] # 等价于 result = [] for a1 in lstt: for a2 in a1: result.append(a2 * a2)

3. 条件判断

过滤条件、三元表达式,可以同时使用

# 过滤条件 lst = [表达式 for item in 可迭代对象 if 过滤条件表达式] # 可迭代对象中满足条件的经表达式处理放进列表中 # 三元表达式 lst = [表达式1 if 条件表达式 else 表达式2 for item in 可迭代对象] # 可迭代对象中所有,满足表达式则经表达式1处理,不满足经表达式2处理 # 同时使用过滤条件、三元表达式 lst = [表达式1 if 条件表达式 else 表达式2 for item in 可迭代对象 if 过滤条件表达式]

4. 应用

矩阵转置:

matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

# 下标i从0-3,分别构造里层列表,里层列表中元素为matrix中每个元素的第i个元素

T = [[item[i] for item in matrix] for i in range(4)]

求100以内素数:

# 筛选2-100中所有数p,满足对于从2-p^0.5的所有数d,p%d都不为0

[p for p in range(2, 100) if all(p%d for d in range(2, int(p**0.5)+1))]


元组 tuple

元组不可变,有序,用()表示

1. 元组创建

  1. tup1 = tuple(序列)

  2. tup1 = (元素1, 元素2, 元素3, ...)

2. 空元组与单元素元组

注意:单元素元组必须在元素后加上逗号,否则会退化成元素本身

  1. 空元组 tup1 =()

  2. 单元素元组 tup2 =(元素1,)

元组中存储的是引用

元组中包含可变对象的引用,这些对象可变,但引用不能改变

# 不改变引用的情形 x = ([1, 2, 3], 4) x[0].append(4) print(x) ''' ([1, 2, 3, 4], 4) ''' # 试图改变引用的情形,报错 x = ([1, 2, 3], 4) x[0] = x[0] + [4] # 此语句返回新列表,会改变原来的引用,报错 print(x) ''' 报错 '''

字典 dict

字典可变,无序# Python3.7之后版本变为有序

字典中元素为键值对,键需为不可变的数据

1. 字典创建

  1. dict1 = dict(键名1=值1, 键名2=值2, 键名3=值3, ...)

  2. dict1 = {键1:值1, 键2:值2, 键3:值3, ...}

2. 空字典

dict1 ={}#表示空字典,注意与空集合 a = set() 区分

3. get, items, keys, values

dict1 = {'A':12, 'C':22, 'W':'S'} # get方法 # dict1.get(键名) # 返回键对应的值,键不存在返回None print(dict1.get('A')) print(dict1.get('B')) ''' 12 None ''' # dict1.get(键名, 默认返回值) # 返回键对应的值,键不存在返回默认值 print(dict1.get('A', 'mmmm')) print(dict1.get('B', 'mmmm')) ''' 12 mmmm ''' # items方法返回字典元素 for item in dict1.items(): print(item) ''' ('A', 12) ('C', 22) ('W', 'S') ''' # items配合序列解包 for key, value in dict1.items(): print(key, value) ''' A 12 C 22 W S ''' # keys方法返回字典的键 print(dict1.keys()) ''' dict_keys(['A', 'C', 'W']) ''' # 直接使用字典名默认使用字典的键 for key in dict1: print(key) ''' A C W ''' # values方法返回字典的值 print(dict1.values()) ''' dict_values([12, 22, 'S']) '''

4. 元素增删改

使用指定键给字典赋值

  1. 键存在:修改其值

  2. 键不存在:创建新键值对

dict1 = {'A':12, 'C':22, 'W':'S'} print(dict1) ''' {'A':12, 'C':22, 'W':'S'} ''' dict1['A'] = 15 print(dict1) ''' {'A':15, 'C':22, 'W':'S'} ''' dict1['B'] = 22 print(dict1) ''' {'A':15, 'C':22, 'W':'S', 'B':22} '''

update方法更新

dict1 = {'A':12, 'C':22, 'W':'S'} dict2 = {'A':17, 'B':21, 'K':'P'} # 将dict1更新dict2中的键值对,存在则修改,不存在则新增 dict1.update(dict2) print(dict1) ''' {'A':17, 'C':22, 'W':'S', 'B':21, 'K':'P'} '''

元素删除del命令,pop, popitem

dict1 = {'A':12, 'C':22, 'W':'S', 'B':21, 'K':'P'} # del命令删除一个键值对 del dict1['A'] print(dict1) ''' {'C':22, 'W':'S', 'B':21, 'K':'P'} ''' # pop方法,根据键名删除键值对并返回一个值,可指定默认值 # dict1.pop(键名, 默认值) print(dict1.pop('C')) print(dict1) ''' 22 {'W':'S', 'B':21, 'K':'P'} ''' # popitem方法,随机删除一个键值对并返回元素(Python 3.7后弹出最后插入的键值对),空字典则KeyError print(dict1.popitem()) print(dict1) ''' 可能为: ('K', 'P') {'W': 'S', 'B': 21} '''

集合set

集合可变,无序

1. 集合创建

set1 = set(序列)

set1 = {元素1, 元素2, 元素3, ...}

2. 空集合

空集合表示为set()# 注意与空字典区分

3. 删除

del set1 # del命令删除整个集合

set1.remove(元素) # 删除指定元素

set1.pop() # 随机删除并返回一个元素

4. 集合运算

&:交

| :并

^:对称差

-:差

例如

{1, 2, 3} & {3, 4, 5} = {3}

{1, 2, 3} | {3, 4, 5} = {1, 2, 3, 4, 5}

{1, 2, 3} ^ {3, 4, 5} = {1, 2, 4, 5}

{1, 2, 3} - {3, 4, 5} = {1, 2}

5. 包含关系

<:左为右的真子集

<=:左为右的子集

例如

{1} < {1, 2, 3} # True,为真子集

{1} <= {1, 2, 3} # True,为真子集,真子集也为子集

{1, 2, 3} < {1, 2, 3} # False,为子集但非真子集

{1, 2, 3} <= {1, 2, 3} # True,为子集

注意与列表、元组区分:列表、元组的<、<=为逐个元素依次比较,为比较关系

例如

(1, 2, 3) < (1, 3) # True,1=1,2<3

(1, 2, 3) < (1, 2, 3, -1) # True, 1=1,2=2,3=3,对应元素相等时,短元组小于长元组。