第二章 运算符表、达式与内置对象
一.内置对象
python中一切都是对象
(一)常量与变量
1.常量:不需要改变也不能改变的字面值,如数字和元组。
2.变量
(1)特点:
值可以变,类型也可以变
不需要声明变量的类型就可以直接赋值
可以使用中文作变量名
//判断类型的方法
type(x)
isinstance(x,int) //内置函数,判断x是否为int类型
(2)内存管理方式:python是基于值的内存管理模式,变量中存储的是地址,而不是具体的值。执行过程是:首先把等号右侧表达式的值计算出来,然后在内存中寻找一个位置把值存储进去,最后创建变量指向这个内存地址。
(3)强类型编程
自动识别赋值运算符右侧表达式变量的类型。
x=1
y=5.3
print(x+y) #6.3
变量被创建后除非显式的进行修改删除,否则将一直保持之前的类型。
(4)变量名的命名规则
变量名必须以字母下划线开头。
变量名中不能有空格或标点符号。
不能使用特殊关键字作为变量名,如内置函数。
不建议使用系统内置模块名。
变量名区分大小写。
(二)数字
1.内置的整数、实数与复数
(1)内存限制:python支持任大的数,具体上限受内存大小限制。
(2)判断相等的依据:两数之差的绝对值是否足够小,尽量避免直接比较两个实数是否相等
abs(0.4-0.3-0.1)<1e-6 #True 1e-6 :1乘以10的负6次方
因为精度问题实数相减会出现误差,但实数相加不会出现误差。
x=0.4
y=0.1
print(x-y) #0.3000000...4
print(x+y) #0.5
(3)复数:与数学运算完全一致。
(4)表达式求值会进行隐式的类型转换。
(5)下划线:在数字中间使用单个下划线作为分隔来提高数字的可读性。
1_2_3_4 #1234
2.分数
3.高精度计算
(三)字符串与字节串
1.特点
(1)python只有字符串类型,没有字符类型。
(2)统计字符串长度时,中文和英文字母都作为一个字符对待,也可以使用中文作为变量名。
2.字符串对象的创建和连接
(1)创建:用单引号和双引号声明字符串,单引号双引号可以相互嵌套。
x='liuzun'
y="zhangjiayou"
(2)连接
+可以实现常量与变量之间的连接
x='liuzun'
y=" love "
str1=x+y+'zhangjiayou'+' forever'
print(str1) #liuzun love zhangjiayou forever
空格只能用于常量与常量之间的连接
str2='liuzun' ' zhangjiayou'
print(str2) #liuzun zhangjiayou
(3)字符串str与字节串bytes之间的转换
二.运算符与表达式---运算符连接表达式
运算符优先级(由高到低):算数运算符→位运算符→成员测试运算符→关系运算符→逻辑运算符
(一)算数运算符
1.+运算符
连接列表、元组、字符串,不能连接集合和字典(集合和字典不可变),且列表元组字符串之间不能连接
x = [1,2,3]
y = [4,5,6]
a = (1,2,3)
b = (4,5,6)
m = {1,2,3}
n = {4,5,6}
print(x+y) #[1, 2, 3, 4, 5, 6]
print(a+b) #(1, 2, 3, 4, 5, 6)
print(m+n) #报错:unsupported operand type(s) for +: 'set' and 'set'
print(y+a) #报错:can only concatenate list (not "tuple") to list
不能连接字符串与数字
'A'+1 #can only concatenate str (not "int") to str
把True和False当0和1处理
2.*运算符:支持可变序列列表、元组、字符串,不支持集合、字典(因为集合和字典不可变且不可重复),表示序列的重复
x=[1,2,3]
y=x*3
print(y) #[1, 2, 3, 1, 2, 3, 1, 2, 3]
3./运算符、//运算符
/表示数学意义上的除法
x=3/2
y=-15/4
print(x) #1.5
print(y) #-3.75
//表示向下取整除法
a=3//2
b=-15//4
print(a) #1(1.5)
print(b) #-4(-3,75)
4.%运算符
整数或实数的求余运算,对实数求余注意精度问题
x=12%5
y=3.2%3
z=3.2%3.1
print(x) #2
print(y) #0.20000000000000018
print(z) #0.10000000000000009
用于字符串格式化,但并不推荐
(二)关系运算符> < ==
1.特点
python关系运算符可以连用,1<3<5等价于1<3and3<5
操作数之间必须可比较
'Hello'>3 #报错:'>' not supported between instances of 'str' and 'int'
具有惰性求值和逻辑短路的特点
2.> < ==的使用
比较大小
'Hello'>'world' #False
'Hello'=='world'#False
'Hello'<'world' #True
[1,2,3]<[1,2,4] #True
成员测试
[1,2,3]<[1,2,3,4] #True,既可以表示列表1小于列表2,也可以表示列表1包含于列表2
[1,2,3]<[1,2,3] #False,两列表相等时不能用于成员测试
print('Hell'<'Hello') #True
(三)成员测试运算符in
判断一个对象是否是另一个对象的元素
print(1 in[1,2,3]) #True
print('H' in 'Hello') #True
print('h' in 'Hello') #False
for i in (3,5,7):
print(i,end=' ') #3 5 7
(四)同一性运算符is
判断两个对象是否相等
x=[300,200,300]
x[0] is x[1] #False
x[0] is x[2] #True
x=[1,2,3]
y=[1,2,3]
z=[1,2,3,4,5]
print(x is y) #True
print(x is z) #False
(五)位运算符与集合运算符
(六)逻辑运算符and or not
逻辑运算符作为连接表达式的条件,具有惰性求值的特点。
1.and
x=3 > 5 and a>3
print(x) #False
2.or
x=3 > 2 or a>3 #只要其中一个True就为True,不考虑其他表达式的对错
print(x) #True
x=3 < 2 or 5>3
print(x) #True
x=3 < 2 or a>3 #一个False一个编译错误
print(x) #Error:name 'a' is not defined
3.not
x=3 not in [1,2,3]
print(x) #False
not 1 #False
not 3 #False
not 0 #True
4.and和or不一定返回True或False,而是得到最后一个被计算的表达式的值
print(3 or 5) #3:第一个为True则结束语句,第一个为False则计算第二个,所以计算完3之后结束or语句
print(3>5 or 7) #7
print(3<5 or 7) #True
print(3 and 5) #5:and语句两边都要运算,所以计算完5之后结束and语句
print(3>5 and 7) #False
print(7 and 3<5) #True
print(3<5 and 7) #7
(七)矩阵乘法运算符
(八)赋值运算符
python不支持先赋值再自增运算i++,i--
支持++i,--i
i++ #SyntaxError: invalid syntax
i-- #SyntaxError: invalid syntax
负负得正原则
x=-5
print(x) #-5
i=--5
print(i) #5
n=------(3+5)
print(n) #8
n=-------(3+5)
print(n) #-8
三.Python常用内置函数用法精要
(一)类型转换
bin():将整数转换为二进制数
oct():将整数转换为八进制数
hex():将整数转换为十六进制数
x = int(float(input("请输入一个自然数:"))) #输入555.0
print("十进制:",x) #555
print("二进制",bin(x)) #0b1000101011
print("八进制",oct(x)) #0o1053
print("十六进制",hex(x))#0x22b
int():将整数、实数、分数(小数)、合法数字及字符串转换为整数
//将整数、实数、分数转换为整数,int()参数列表中只有一个参数
x=3.2
print(int(x)) #3
x=-3.2
print(int(x)) #-3
//将字符串转换为整数时:int('字符串',base),将字符串按base进制转换为十进制
//base的值为0或2-36的整数,0表示按字符串隐含进制进行转换
x=555
y=bin(x)
z=int(y,2) #把2进制数转化为十进制整数
m=int(y,0) #y的隐藏进制为2进制
print(y) #0b1000101011
print(z) #555
print(m) #555
float():将整数、数字字符串、分数(小数)、合法数字及字符串转换为实数
complex():生成复数
x=complex(3,5)
y=complex('nan') #非数字,若第一个参数为字符串则第不能有第二个参数
print(x) #(3+5j)
print(type(x)) #<class 'complex'>
print(y) #(nan+0j)
str():将任意类型参数转换为字符串类型
//整数转换字符串
x=1234
print(type(str(x))) #<class 'str'>
print(str(x))
//列表转换字符串
x=[1234]
print(type(str(x))) #<class 'str'>
print(str(x))
//元组转换字符串
x=(1234)
print(type(str(x))) #<class 'str'>
print(str(x))
//集合转换字符串
x={1234}
print(type(str(x))) #<class 'str'>
print(str(x))
////字符串转换字符串
x='1234'
print(type(str(x))) #<class 'str'>
print(str(x))
////分数(小数)转换字符串
x=1.234
print(type(str(x))) #<class 'str'>
print(str(x))
ord():返回单个字符的Unicode码
print(ord('a')) #97
print(ord('A')) #65
print(ord('刘')) #21016
chr():返回Unicode码对应的字符
chr(65) #'A'
chr(97) #'A'
chr(21016) #'刘'
ascii():把对象转换为ASCII码表示
bytes():
生成字符串
把指定对象转换为字符串
把字节串转换为列表
x='刘遵'.encode()
print(x) #b'\xe5\x88\x98\xe9\x81\xb5',是一个字节序列,表示一种编码方式,这里使用的是UTF-8编码。UTF-8是一种可变长度的编码方式,每个字符可以由1个到4个字节组成。
print(list(x)) #[229, 136, 152, 233, 129, 181]
list()、tuple()、dict()、set()、frozenset()把其他类型的数据转换为列表、元组、字典、可变、不可变集合
注意:转换为字典时,被转换的对象必须只能有两个元素
//frozenset
x = {1,2,3,4,5}
y=frozenset(x)
y.add(7) #Error:'frozenset' object has no attribute 'add'
//dict
x=['a','b','c','d','e']
y=enumerate(x,0)
print(dict(y)) #{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
type()、isinstance()
type():
查看参数类型
type(3) #<class 'int'>
判断是否是某数据类型的实例(可能不可行)
type({3}) in (list,tuple,dict) #False
ininstance( 对象的实例,数据类型 ):
判断对象的实例是不是某种数据类型
在Python中,isinstance(object, classinfo) 是一个内置函数,用于检查一个对象是否是一个特定的类或者类族的一部分。
在你的例子 isinstance(3, float or int) 中,float or int实际上是先进行一个逻辑判断。Python会先判断float是否为真,如果为真,那么就判断3是否是浮点数类型,否则(即float为假时)就判断3是否是整数类型。
但实际上,你应该分别使用 isinstance(3, float) 和 isinstance(3, int) 来检查3是否分别是浮点数或整数。这样的语法会更清晰,更符合Python的编程习惯。
#判断3是不是int类型
x=isinstance(3, int)
print(x) #True
//
y=isinstance(3, float or int) //
print(y) #False
y=isinstance(3, int or float)
print(y) #True
//判断数据是否是这三个数据类型之一
z=isinstance(3j,int,float,complex)
print(z) #True
(二)最值求和
max():
计算列表、元组或包其它含有限个元素的可迭代对象中所有元素的最大值,支持default参数和key参数
//生成10个1-99之内的数
from random import randint
x=[randint(1,100) for i in range(10)]
print(max(x))
key参数:指定寻找的标准,可以用lambda表达式对标准进行定义
y=['1','111',"111"]
print(max(y,key=len)) #按字符串长度找最大值
default参数:指定可迭代对象为空时的返回值
z=[]
print(max(z,key=len,default='NULL'))
min():
计算列表、元组或包其它含有限个元素的可迭代对象中所有元素的最小值,支持default参数和key参数
//生成10个1-99之内的数
from random import randint
x=[randint(1,100) for i in range(10)]
print(min(x))
key参数:指定寻找的标准,可以用lambda表达式对标准进行定义
y=['1','111',"111"]
print(min(y,key=len)) #找字符串长度最小的元素
default参数:指定可迭代对象为空时的返回值
z=[]
print(min(z,key=len,default='NULL'))
sum():
计算列表、元组或包其它含有限个元素的可迭代对象中所有元素的和
from random import randint
x=[randint(1,100) for i in range(10)]
print(sum(x))
(三)基本输入输出
input():输入函数
print():输出函数
//enumerate对象的使用
for i in enumerate(range(10),7):
print(i,end=" ") #(7, 0) (8, 1) (9, 2) (10, 3) (11, 4) (12, 5) (13, 6) (14, 7) (15, 8) (16, 9)
print('\n')
for j in enumerate(range(10),7):
print(j,end='') #(7, 0)(8, 1)(9, 2)(10, 3)(11, 4)(12, 5)(13, 6)(14, 7)(15, 8)(16, 9)
(四)排序与逆序
sorted():
对可迭代对象按默认升序或其它顺序排序,返回一个新的列表
按默认升序排序
from random import randint
x=[randint(1,100) for i in range(10)]
print(x) #例子:[88, 39, 55, 80, 63, 91, 89, 66, 83, 39]
y=sorted(x) #例子:[39, 39, 55, 63, 66, 80, 83, 88, 89, 91]
print(y)
按降序排序
from random import randint
x=[randint(1,100) for i in range(10)]
print(x) #例子:[58, 80, 27, 54, 63, 42, 65, 28, 11, 58]
y=sorted(x,reverse=True)
print(y) ##例子:[80, 65, 63, 58, 58, 54, 42, 28, 27, 11]
按字符串长度排序顺序排序
from random import randint
x=[randint(1,100) for i in range(10)]
print(x) #例子:[92, 49, 41, 68, 86, 34, 76, 29, 5, 86]
y=sorted(x,key=str)
print(y) #例子:[29, 34, 41, 49, 5, 68, 76, 86, 86, 92]
用lambda表达式定义标准进行排序
//按字符串长度进行排序
x=['a','bb','c','dd','ee','fff','g','hhh']
print(x)
y=sorted(x,key=lambda y:len(y)) #y来自于x,按字符串y的长度排序,长度相等的相对位置不变
print(y)
//将其他数据类型转换为字符串后,按字符串长度排序
from random import randint
x=[randint(1,100) for i in range(10)]
print(x)
y=sorted(x,key=lambda y:len(str(y)))
print(y)
z=sorted(x,key=lambda y:len(str(y)),reverse=True) #按字符串长度逆序排列
print(z)
(五)枚举 enumerate()
枚举返回的是元组
enumerate(可迭代对象,索引的初始值(默认值为0)):
将可迭代对象的元素取出并标上序号,返回新的可迭代的enumerate对象
from random import randint
x=[randint(1,100) for i in range(10)]
y=list(enumerate(x))
z=list(enumerate(range(10),3)) #给数字0-9从3开始编号
print(y)
print(z)
(六)map(),reduce(),filter()
map、filter返回的是新的可迭代对象,reduce返回的不是可迭代对象
map(映射关系,可迭代对象1,可迭代对象2,...)
map() must have at least two arguments.:map至少含有两个参数
将x按某种函数关系映射到y
//y=x映射
x=[1,3,5,7,9]
y=map(lambda x:x,x)
print(x)
print(list(y))
//y=2x映射
x=[1,3,5,7,9]
y=map(lambda x:x*2,x)
print(x)
print(list(y))
//z=x+y映射
x=[1,3,5,7,9]
y=[2,4,6,8,10]
z=map(lambda item1,item2:item1+item2,x,y) //item1,item2是形参,用于接收可迭代对象x,y内的值
print(x)
print(y)
print(list(z))
//y=(x!=5),返回值是布尔值
x=[1,3,5,7,9]
y=map(lambda x:x!=5,x)
print(x)
print(list(y))
reduce(运算关系,可迭代对象)
需要函数库导入:from functools import reduce
运算关系可以导入operator库,也可以自己定义
对可迭代对象元素进行运算
from functools import reduce
#求和运算
import operator
x=reduce(operator.add,range(10)) #operator
print(x) #45
x=reduce(lambda x,y:x+y,range(10)) #lambda函数,map函数中的x,y不可以来自同一个可迭代对象
y=reduce(lambda x,y:x*y,range(1,10))
print(x) #45,只计算了x相加
print(y) #362880,只计算了x相乘,map函数中的x,y不可以来自同一个可迭代对象,x来自range(10),则y不能来自range(10),那么y就没有被定义
filter(过滤条件,可迭代对象)
将可迭代对象中不符合过滤条件的元素删除,符合条件的留下
x=filter(lambda x:x%2==0,range(10))
print(list(x)) #[0, 2, 4, 6, 8]
(七)range函数
(八)zip()
zip(可迭代对象1,可迭代对象2,可迭代对象3.....)
将多个可迭代对象对应位置上的元素压缩至一个元组,返回一个新的zip对象。
x=['a','b','c','d','e']
y={1,2,3,4,5,6}
z=('first','second','third','fourth','fifth')
result=zip(x,y,z)
print(result) #<zip object at 0x00000170C0B1FE40>
print(list(result)) #[('a', 1, 'first'), ('b', 2, 'second'), ('c', 3, 'third'), ('d', 4, 'fourth'), ('e', 5, 'fifth')]
第三章 详解python序列结构
- python序列可分为:有序序列和无序序列 ; 可变序列和不可变序列
- 有序序列(ordered sequence)是指元素之间具有顺序关系的序列。这意味着在序列中,每个元素都有一个特定的位置,并且序列中的元素按照它们在序列中的顺序进行排列。
- 有序是指元素之间的位置关系而不是数值关系。
y=[1,3,2,5,'无序序列',4,'有序序列']
for i in y:
print(i,end=' ') #1 3 2 5 无序序列 4 有序序列
- 在Python中,列表、元组、range对象都是有序序列,而集合、字典则不是。但是尽管集合是无序的,但集合中的元素仍然按照它们被添加到集合中的顺序进行排列。
- 有序序列支持双向索引,即可用正数、负数表示索引。0为正向索引的第一个下标,-1为负向索引的第一下标。
y=[1,2,3,4,5] #定义一个列表
print(y[0]) #1
print(y[-1]) #5
print(y[-2]) #4
一.列表:打了激素的数组
(一)列表的特点
1.存储结构:包含若干个元素的有序连续内存空间
2.存储内容:同一列表内数据的类型可以各不相同,可以同时含基本类型元素以及其他任意类型的对象
x=['2003',10,'13 男',['2003',10,'02 女'],('济','宁'),3.5,'年',{'学校 :qlu'},{'学校':'art'}]
for i in x:
print(i,end=" ") #2003 10 13 男 ['2003', 10, '02 女'] ('济', '宁') 3.5 年 {'学校 :qlu'} {'学校': 'art'}
3.基于值的的自动内存管理模式:列表中存储的是值的引用,引用都是类型相同的数值,所以列表中各元素可以是不同类型的数据。
4.列表的增删:当列表增删时,列表对象自动进行扩展(元素后移)和收缩(元素前移),但效率不高,尽量在列表尾部进行增删操作。
5.缺点:列表虽功能强大,但负担比较重,开销较大。
(二)列表的基本操作
1.列表的创建
用=直接进行创建
x=[1,2,3]
用list方法转化创建
x=(1,2,3)
y=list(x)
print(x) #(1,2,3)
print(y) #[1,2,3]
#字典转化为列表
x={'a' : 1,'b' : 2,'c' : 3}
y=list(x)
z=list(x.items())
print(y) #['a', 'b', 'c']
print(z) #[('a', 1), ('b', 2), ('c', 3)]
2.列表的删除
del 命令:删除后不仅是清空数据,也释放了地址。
x=[1,3,2,7,4,5,11,9]
print(x) #[1, 3, 2, 7, 4, 5, 11, 9]
del(x)
print(x) #NameError: name 'x' is not defined
3.列表元素的访问
用下标进行访问
y=[1,2,3,4,5] #定义一个列表
print(y[0]) #1
print(y[-1]) #5
print(y[-2]) #4
用循环进行访问
x=[1,3,2,7,4,5,11,9]
for i in x:
print(i,end=' ') #1 3 2 7 4 5 11 9
4.列表的常用方法
元素增加
都属于原地操作,不返回新的列表
append(value):在列表尾部追加一个元素value
x=[1,2,3,4,5,6]
x.append(7)
print(x) #[1, 2, 3, 4, 5, 6, 7]
insert(index,value):在index处插入一个元素value
x=[1,2,3,4,5,7]
x.insert(5, 6) #在索引5处加一个6
print(x) #[1, 2, 3, 4, 5, 6, 7]
extend()在列表尾部追加一个可迭代对象中的所有元素
x=[1,2,3,4,5,7]
y={'a','b','c'}
z={'d' : 1,'e' : 2,'f' : 3}
s=(8,9,10)
print(x)
x.extend(y)
print(x)
x.extend(z)
print(x)
x.extend(s) #只能追加键值
print(x)
x.extend(range(11,14))
print(x)
元素删除
都属于原地操作,不返回新的列表
pop(index):删除并返回index位置上的元素
x=[1,2,3,4,5,7]
y=x.pop(5)
print('弹出的元素是:',y) #弹出的元素是: 7
print(x) #[1, 2, 3, 4, 5]
remove(value):删除第一个与value相同的元素
x=[1,2,3,4,5,7,7]
y=x.remove(7)
print(x) #[1, 2, 3, 4, 5, 7]
clear():清空列表中所有元素
x=[1,2,3,4,5,7,7]
x.clear()
print(x) #[]
查找
count(value):返回value出现的次数
x=[1,2,3,4,5,7,7]
y=x.count(7)
print('7出现的次数是:',y) #7出现的次数是: 2
index(value):返回value首次出现的索引
x=[1,2,3,4,5,7,7]
y=x.index(7)
print('7出现的位置是:',y) #7出现的位置是: 5
排序与逆序
原地操作,不返回新的列表
sort()方法与reverse()方法:与sorted、reversed内置函数类似,只是在原列表内操作,不返回新的列表
import random
x=list(range(11))
print('原列表的顺序是:',x) #原列表的顺序是: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
random.shuffle(x) #属于原地操作
print('打乱后列表的顺序是:',x)#打乱后列表的顺序是: [2, 9, 0, 6, 7, 1, 4, 10, 3, 5, 8]
x.sort()
print('排序后列表的顺序是:',x) #排序后列表的顺序是 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x.reverse()
print('逆序后后列表的顺序是:',x) #逆序后后列表的顺序是: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
sort方法与sorted函数区别体现
import random
#sorted函数
x1=list(range(11))
random.shuffle(x1)
y1=sorted(x1)
print(x1) #保留了原来的列表数据
print(y1) #y1得到了返回值,是排序后新的列表
#sort方法
x2=list(range(11))
random.shuffle(x2)
y2=x2.sort()
print(x2) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(y2) #None,y2不得到返回值
复制
都不属于原地操作
引用:列表中元素的首地址
copy():
copy是浅复制:把列表中所有元素的引用复制到新列表中,不属于原地操作
特点:非空、非单元素子列表元素改变相互影响,单字符改变不相互影响
x=[1,2,3,[4,5]]
y=x.copy()
x[3].append(6) #y改变
x[0]=7 #y不改变
x.append(8) #y不改变
print(x) #[7, 2, 3, [4, 5, 6], 8]
print(y) #[1, 2, 3, [4, 5, 6]]
单元素列表和空列表的赋值修改的影响
x=[1,2,3,[4,5],[6]]
print('x列表的初始值:',x) #x列表的初始值: [1, 2, 3, [4, 5], [6]]
y=x.copy()
y[4]=[7] #首值变,引用已经修改
y[4].append('不相互影响') #y[4]的引用已经发生修改,对y子列表进行操作不影响x
y[3].append('相互影响')
print('y列表改变后的x列表:',x) #y列表改变后的x列表: [1, 2, 3, [4, 5, '相互影响'], [6]]
print('y列表改变后:',y) #y列表改变后: [1, 2, 3, [4, 5, '相互影响'], [7, '不相互影响']]
x=[1,2,3,[4,5],[6],[]]
print('x列表的初始值:',x)
y=x.copy()
y[3]=[] #首值变,引用已经修改
y[4].append('不相互影响') #y[4]的引用已经发生修改,对y子列表进行操作不影响x
y[3].append('相互影响')
print('y列表改变后的x列表:',x)
print('y列表改变后:',y)
copy.deepcopy(list):
需要导入函数copy: import copy
copy.deepcopy()函数是深复制:对列表中所有元素进行递归,把所有值复制到新列表中,新列表与原列表相互独立互不影响。
copy.deepcopy()函数的结果是两份不同的引用指向两个元素相同列表。
import copy
x=[1,2,3,[4,5]]
y=copy.deepcopy(x)
x[3].append(6)
x[0]=7
x.append(8)
y.append(10)
print(x) #[7, 2, 3, [4, 5, 6], 8]
print(y) #[1, 2, 3, [4, 5], 10]
将一个相同的列表赋值给两个变量
这两变量相互独立互补影响
用=赋值
把一个列表变量x赋值给列表变量y,则x与y存储的引用相同指向同一个列表,对其中一个做任意修改都会使另一个列表做相应的修改。
与copy()方法相同都是对引用进行操作,但是copy()方法的结果是两份相同的引用x,y指向同一组列表变量,而=赋值后的结果是x与y共用同一份引用指向同一组列表变量。所以copy方法只有在对子列表操作时才相互影响,而对单元素进行操作时互不影响。
x=[1,2,3,[4,5]]
y=x
x[3].append(6)
x[0]=7
x.append(8)
y.append(10)
print(x) #[7, 2, 3, [4, 5, 6], 8, 10]
print(y) #[7, 2, 3, [4, 5, 6], 8, 10]
4.列表对象支持的运算符
追加元素
+:实现列表元素的增加,涉及大量元素复制,效率非常低,不属于原地操作。
x=[1,2,[3,4,5]]
x+[6]
print(x) #[1, 2, [3, 4, 5]],列表元素未发生改变,不属于原地操作
print(id(x)) #原地址2303579337664
x=x+[6]
print(x) #[1, 2, [3, 4, 5], 6]
print(id(x)) #地址发生化2303579340224
x=x+[[7,8,9]]
print(x) #[1, 2, [3, 4, 5], 6, [7, 8, 9]],可一次增加大量元素
print(id(x)) #地址发生化2303579340608
+=:实现列表的追加,与extend方法一样高效,属于原地操作。
x=[1,2,[3,4,5]]
print(id(x)) #2303578433600
x+=[6]
print(x) #原地操作,[1, 2, [3, 4, 5], 6]
print(id(x)) #2303578433600
元素重复运算符
:列表与整数相表示列表的重复,返回新的列表,不属于原地操作
*=:也表示列表重复,但属于原地操作
成员测试符 in
用于查询列表中是否包含某个元素,查询时间随着列表长度的增加而线性增加,同样的操作对集合而言则是常数级的。
内置函数
max()
min()
sum()
len():返回列表中元素个数
zip()
enumerate()
map()
filer()
all():测试列表中所有元素是否等价于True
在Python中,以下是一些被视为等价于 True 的值:
- 非空字符串(例如:"hello")
- 非零数字(例如:1,2,3,-1,-2,-3等)
- 非空集合(例如:{1, 2, 3}, {'a', 'b', 'c'}等)
- 非空列表(例如:[1, 2, 3],[1, 'a', 3.14]等)
- 非空元组(例如:(1, 'a'), ('hello', 'world')等)
- 非空字典(例如:{'name': 'Alice', 'age': 25}等)
- 非空枚举(在Python 3.7以后的版本中引入)
- 非空生成器(通过调用一个生成器函数或使用内置的
iter()函数得到的生成器对象) - 非空的上下文管理器(通过使用
with关键字和__enter__()和__exit__()方法定义的上下文管理器) - 非空的类型(例如:None,整数,浮点数,字符串,布尔值,集合,列表,元组,字典,生成器,上下文管理器等)
x=[1,2,[3,4,5],'liu',(7,8,9),{'zun'},{'a' : 'you'}]
print(all(x)) #True
y=[1,2,[3,4,5],'liu',(7,8,9),{'zun'},{'a' : 'you'},[],{},()]
print(all(y)) #False
any(): 测试列表中是否有元素等价于True
以下是被视为等价于 False 的值:
- 空字符串(例如:"")
- 零或负零
- 空集合(例如:set(),{}等)
- 空列表(例如:[]等)
- 空元组(例如:()等)
- 空字典(例如:{}等)
- None
- 布尔值
False - 空生成器(通过调用一个生成器函数或使用内置的
iter()函数得到的生成器对象,如果它不产生任何元素) - 空的上下文管理器(通过使用
with关键字和__enter__()和__exit__()方法定义的上下文管理器,如果它不执行任何操作)
y=[1,2,[3,4,5],'liu',(7,8,9),{'zun'},{'a' : 'you'},[],{},()]
print(any(y)) #True
(三)列表推导式
1.概念
列表推导式也称列表解析式,可以使用非常简洁的方式对列表或其他可迭代对象进行遍历、过滤或再次计算
2.形式
[ 表达式 for 表达式中的元素 in 可迭代对象 if condition过滤条件 ]
形式可以分为三部分,每部分之间的分隔符是空格
- 表达式---表达式的结果是列表中的元素
- for至可迭代对象---相当于变量取值的声明
- if条件---过滤条件
3.应用
实现嵌套列表的平铺
降低列表的深度
vec=[[1,2,3],[3,4,5],[6,7,8]]
x=[num for i in vec for num in i] #i取自vec,num取自i
print(x) #[1, 2, 3, 3, 4, 5, 6, 7, 8]
若有多级嵌套或者多级子列表嵌套深度不同,则需要使用函数递归实现
过滤不符合条件的元素
使用if condition 过滤
过滤数字
from random import randint
x=[randint(1,100) for i in range(10)]
print('过滤前的列表:',x) #过滤前的列表: [98, 11, 10, 98, 90, 73, 97, 74, 17, 88]
y=[i for i in x if i>=50]
print('过滤后的列表',y) #过滤后的列表 [98, 98, 90, 73, 97, 74, 88]
过滤最高成绩
scores={'刘遵' : 97.2,'张嘉佑' : 99.3,'张敏': 100}
y=max(scores.values())
print(y)
x=[name for name ,score in scores.items() if score==y]
print(x)
寻找列表中最大元素的位置
from random import randint
x=[randint(1,10) for i in range(20)]
print(x) #[3, 3, 10, 3, 7, 9, 8, 10, 8, 7, 1, 6, 6, 10, 8, 7, 2, 10, 10, 7]
maxSum=max(x)
y=[index for index,num in enumerate(x) if num==maxSum] #index与num的顺序不能改变,与enumrate函数的默认参数顺序相同
print('最大元素的位置是:',y) #最大元素的位置是: [2, 7, 13, 17, 18]
同时遍历多个列表或可迭代对象
两个for语句之间的分隔符为空格
result1=[x*y for x in[1,2,3] for y in {4,5,6}]
result2=[(x,y) for x in[1,2,3] for y in {4,5,6}]
print(result1) #[4, 5, 6, 8, 10, 12, 12, 15, 18]
print(result2) #[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
if条件只限制其前面,最近的一个for语句
res=[(x,y) for x in[1,2,3] if x==1 for y in {4,5,6} if y!=x]
print(res)
矩阵转置
表达式可以为函数或复杂表达式
[f(v) for v in [1,2,-1,4] if v>0]
支持文件对象迭代
生成100以内的所有素数
[p for p in range(2,100) if 0 not in
[p%d for d in range(2,int(sqirt(p)+1)]]
(四)切片
切片的操作都是列表间的操作
1.形式
[start:end:step]
start:起始位置,为0时可省略
end:结束位置(不包括),为列表长度时可省略
step:步长,为1时可省略
第一个::不可省略
第二个::step为1时,可省略
2.特点
(1)当step为负数时,表示反向切片,但要注意start指向的元素要在·Q1stop指向元素的右侧
aList=[1,2,3,4,5]
y=aList[4:1:-1]
z=y=aList[-1:1:-1] #-1和4都指向第5个元素
print(y) #[5, 4, 3]
print(z) #[5, 4, 3]
(2)切片操作不会因为下标越界而抛出异常,而是在列表尾部和头部进行截断。
aList=[1,2,3,4,5]
x=aList[:100]
print(x) #[1, 2, 3, 4, 5]
3.切片操作
(1)获取列表元素
不属于原地操作,返回有一个新的列表
(2)为列表增加元素
属于原地操作
在头部增加,stop为0
aList=[1,2,3,4,5]
aList[:0]=[-3,-2,-1,0]
print(aList) #[-3, -2, -1, 0, 1, 2, 3, 4, 5]
在尾部增加,start为列表长度
aList=[1,2,3,4,5]
aList[len(aList):]=[6,7,8,9]
print(aList) #[1, 2, 3, 4, 5, 6, 7, 8, 9]
在中间插入,一次只能插入一个,start=stop=等于插入位置
aList=[1,2,3,4,6]
aList[4:4]=[5]
print(aList) #[1, 2, 3, 4, 5, 6]
(3)替换,修改列表中的元素
属于原操作
操作前要看切片是否连续:step为1或-1时切片连续,其他切片不连续
切片不连续时
替换位置的个数要与提供的元素个数相等
//要替换的位置为0,2,4三个位置,但提供了四个元素
x=[1,3,5,7,9]
x[::2]=[2,4,6,7]
print(x) #ValueError: attempt to assign sequence of size 4 to extended slice of size 3
//要替换的位置为0,2,4三个位置,提供了三个元素
x=[1,3,5,7,9]
x[::2]=[2,4,6]
print(x) #[2, 3, 4, 7, 6]
//要替换的位置为0,2,4三个位置,提供了两个元素
x=[1,3,5,7,9]
x[::2]=[2,4]
print(x) #ValueError: attempt to assign sequence of size 2 to extended slice of size 3
切片连续时
替换位置的个数要与提供的元素个数不需要相等
//替换位置个数大于提供元素个数,替换位置上的元素被覆盖,多出的替换位置元素消失
aList=[1,2,3,4,5]
aList[1:4]=[21,27]
print(aList) #[1, 21, 27, 5]
//替换位置个数等于提供元素个数
aList=[1,2,3,4,5]
aList[1:3]=[21,27]
print(aList) #[1, 21, 27, 4, 5]
//替换位置个数小于提供元素个数,只有替换位置上的元素被覆盖,多出的提供元素仍然进入列表
aList=[1,2,3,4,5]
aList[1:3]=[21,27,35,47]
print(aList) #[1, 21, 27, 35, 47, 4, 5]
(4)map、zip、filter函数的应用
map(映射关系,可迭代对象)
aList=['a',1,'b',2,'c',0]
aList[1::2]=map(lambda x:x!=0,range(3)) #x来自于可迭代对象range(0)
print(aList) #['a', False, 'b', True, 'c', True]
zip(iter1,iter2,...itern)
aList = ['a', 1, 'b', 2, 'c', 0]
new_elements = list(zip(('刘遵','张嘉佑','张敏'),('男','女','女'),['20','20','45'])) # 将zip对象转换为列表
aList[1::2] = new_elements # 将新的元素列表插入到原列表的指定位置
print(aList)
为什么不行?
aList = ['a', 1, 'b', 2, 'c', 0]
x=('刘遵','张嘉佑','张敏')
y={20,20,45} #2023 12 28 因为集合不能重复
z=['男','女','女']
new_elements = list(zip(x,y,z)) # 将zip对象转换为列表
aList[1::2] = new_elements # 将新的元素列表插入到原列表的指定位置
print(aList)
filter(过滤条件,iter)
(5)使用切片删除列表中的元素
=[]删除
aList=[3,5,7,9,11]
aList[0:3]=[]
print(aList) #[9, 11]
del关键字删除
aList=[3,5,7,9,11]
del aList[0:3]
print(aList) ##[9, 11]