第四-五章 字典、集合与控制语句
1.字典:由“键值对”组成的无序可变序列,其中可以通过“键对象”找到相应的“值对象”进行操作,但要注意“键”为不能重复的任意不可变数据(整数、浮点数、字符串、元组),“值”为可变对象且可以重复。
字典的创建:通过{'name':'Lisa','age':12,'city':'NewYork'}、dict(name='Lisa',age=12,city='NewYork')创建字典;使用dict(zip(包含键对象的列表,包含值对象的列表))创建字典;通过dict.fromkeys(['name','age','job']) 创建有键无值得字典。
字典的访问:通过的d['keyname']获得相应值;通过d.get('keyname'[,'不存在默认返回对象']);通过d.items()/d.keys()/d.values()列出字典所有键值对/键/值;通过len()检查键值对的数目;通过'keyname' in/not in d检测“键”是否在字典中。
字典元素添加、修改、删除:给字典新增“键值对”,如果“键”已经存在,则覆盖旧的键值对;如果“键”不存在, 则新增“键值对”。 a['Newkeys']='Newvalue';使用a.update(b)更新字典,将原有的键保留,对应的值替换为b的,并将新键值对更新入字典;使用del(d['keyname'])删除对应的键值对,d.pop('keyname')可以返回指定的值对象,删除对应字典中的键值对,或者用d.clear()删除字典对象。可通过d.popitem()一个接一个地移除并处理项。
2.序列解包:方便对多个变量赋值(元组(x,y,z)=(1,2,3)列表[x,y,z]=[1,2,3])
对字典序列的解包(对键操作)
d={'国籍':'中国','年龄':25,'工作':'老师'}
a,b,c=d #对键进行解包
l=[a,b,c]
print(l)
e,f,g=d.values() #对值进行解包
m=[e,f,g]
print(m)
h,i,j=d.items() #对键值对进行解包
n=[h,i,j]
print(n)
3.字典核心(散列表:总有空白元素的数组,每个单元叫由键对象和值对象构成的bucket)底层原理:
(I)将一个键值对放进字典的底层过程:首先要通过hash('keyname')计算对应键的散列值,之后根据字典序列的长度从hash(‘keyname’)对应2进制码的右侧获取相应长度的二进制数,取此数作为偏移量,查询当前偏移量所指的bucket是否为空,如若空则将键值对放入其中,若非空,继续从hash(‘keyname’)对应2进制码再往左取相应位数的二进制码,直至找到可以放入键值对的bucket为止。当列表已占位的bucket数目占总数2/3左右时,数组就需要扩容。
(II)根据键查找键值对的过程:第一步,我们仍然要计算“keyname”对象的散列值, 假设数组长度为 8,我们可以拿计算出的散列值的最右边 3位数字作为偏移量,若为“101”,十进制是数字 5。我们查看偏移量 5,对应的bucket 是否为空。如果为空,则返回None。如果不为空, 则将这个bucket的键对象计算对应散列值,和我们的散列值进行比较,如果相等。则将对应“值对象”返回。如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后仍然没有找到,则返回 None。
注意:(1) 键必须可散列: 整数、浮点数、字符串、元组,都是可散列的。自定义对象需要支持下面三点:支持 hash()函数、支持通过__eq__()方法检测相等性、若a==b为真,则 hash(a)==hash(b)也为真。 (2)字典在内存中开销巨大,典型的空间换时间。(3)键查询速度很快。(4)往字典里面添加新建可能导致扩容,导致散列表中键的次序变化。因此,不要在遍历字典的同时进行字典的修改(即要先遍历字典取出数据后再进行修改)。
4.集合(可以看做只有键没有值的字典对象,所以不可重复):集合的创建可通过{}实现;也可通过set(list())将元组、列表转换为集合;a.add('s')用于添加元素;a.remove('20')用于删除指定集合元素。两集合的并集a|b、两集合的交集a&b、两集合的差集a-b(注意差集a-b绝大多数情况下不等于b-a,原因是差集是被减集合去掉与减集合相同的元素所得到的,主要看两集合差异度和被减集合情况)。
5.作业:
(1)
(2)
print(list(range(30,90,10)))
(3)a=[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
(4)
l1=['高小一',18,30000,'北京']
l2=['高小二',19,20000,'上海']
l3=['高小五',20,10000,'深圳']
a=[l1,l2,l3]
(5)元组:不可变序列,因此不具有数据的修改操作;列表:可变序列,具有数据的修改操作,可以随时增加或者删减元素。但两者都是是一块用来存放多个值的连续的内存空间,即可迭代序列。
(6)d=dict(支出金额=300.15,支出日期='2020.10.18',支出人='高小七')
(7)
'''
r1={'姓名':'高小一','年龄':18,'薪资':30000,'城市':'北京'}
r2={'姓名':'高小二','年龄':19,'薪资':20000,'城市':'上海'}
r3={'姓名':'高小五','年龄':20,'薪资':10000,'城市':'深圳'}
a=[r1,r2,r3]
for x in range(len(a)):
for y in a[x]: #遍历字典的所有键
print(a[x].get(y),end='\t')
print()'''
r1=dict(姓名='高小一',年龄=18,薪资=30000,城市='北京')
r2=dict(姓名='高小二',年龄=19,薪资=20000,城市='上海')
r3=dict(姓名='高小五',年龄=20,薪资=10000,城市='深圳')
l=[r1,r2,r3]
for m in l:
for n in m: #这里的n就是字典对象的键
print(m[n],end='\t')
print()
(8)(9)略
6.控制语句(开发环境:pycharm):
(1)选择结构(核心为判断条件表达式):包括单分支、多分支与双分支3种类型。
单分支结构语法:if 条件表达式:
(TAB)语句/语句块
在选择和循环结构中,条件表达式的值为 False的情况如下: False、0、0.0、空值 None、空序列对象(空列表、空元祖、空集合、空字典、空字符串)、空range 对象、空迭代对象。(注意:‘False’字符串等价于布尔值True;条件表达式中只能不能含赋值符‘=’,可以含等值比较符‘==’)
双分支结构语法:if 条件表达式:
(TAB)语句/语句块
else:
(TAB)语句/语句块
利用三元条件运算符:实现输入一个数字,小于10,则打印该数字;大于 10,则打印‘数字太大’。
a=input('请输入一个数字:')
print(a if int(a)<10 else '数字太大')
多分支选择结构语法:if 条件表达式:
(TAB)语句/语句块
elif:
(TAB)语句/语句块
......
elif:
(TAB)语句/语句块
else:语句/语句块
注意:多分支结构,几个分支之间是有逻辑关系的,不能随意颠倒顺序。
选择结构嵌套:最重要的是要控制好不同级代码的缩进量。
(2)循环结构:如果符合条件,则反复执行循环体里的语句。在每次执行完后都会判断一次条件是否为 True,如果 为True则重复执行循环体里的语句(为避免死循环,循环体中至少包含改变条件表达式的语句)。(对于循环结构而言,尽量减少内部计算,尤其是在嵌套环境中,内层循环甚至考虑提到外层。)
while循环:while 条件表达式:
(TAB)循环体语句/语句块
for循环:通常用于可迭代对象的遍历。语法:for 变量 in 可迭代对象:循环体语句
利用嵌套循环打印九九乘法表:
for m in range(1,10):
for n in range(1,10):
if n<=m:
print('{0}×{1}={2}'.format(n,m,n*m),end='\t')
print()
continue与break的区别:continue用于脱离最近的一次循环,进入下次循环中;break为跳出整个循环,有嵌套时要注意是跳出最近一层的循环。(常用与while True结构中)
循环else语句:while、for 循环可以附带一个 else 语句(可选)。如果for、while语句没有被break 语句 结束,则会执行else子句,否则不执行。
(3)zip()并行迭代(zip()函数在最短序列“用完”时就会停止):
(4)推导式创建序列:列表推导式生成列表对象,语法: [表达式 for item in 可迭代对象 ]
生成位于x∈(1,9),y∈(1,9)区域所有整数坐标点:
loc=[(r,l) for r in range(1,10) for l in range(1,10)]
for y in loc:
print(y)
字典推导式{key_expression : value_expression for 表达式 in 可迭代对象}
集合推导式除{}外与列表生成式一致。
生成器推导式(只能迭代一次,且返回值为生成器对象,不能返回元组):
(表达式 for item in 可迭代对象 )
7.作业:
(1)略(2)(4)思想相同代码如下:
score=input('请输入一个学生的成绩:')
s=float(score)
while s>100 or s<0:
score=input('输入错误!请重新输入学生成绩:')
s = float(score)
if s<60:
grade='不及格'
elif s<80:
grade='及格'
elif s<90:
grade='良好'
else:grade='优秀'
print('录入学生成绩为{0},相应的等级为{1}'.format(score,grade))
(3)
x=input('请输入点的横坐标:')
xx=float(x)
y=input('请输入点的纵坐标:')
yy=float(y)
if xx==0:c='纵轴上'
elif yy==0:c='横轴上'
elif xx>0 and yy>0:c='第一象限'
elif xx > 0 and yy < 0:c='第二象限'
elif xx < 0 and yy < 0:c = '第三象限'
else:c = '第四象限'
print('({0},{1})点位于{2}'.format(x,y,c))
(5)
num=1
sum_total=0
sum_oushu=0
sum_jishu=0
while num<=100:
sum_total+=num
if num%2==0:
sum_oushu += num
else:
sum_jishu += num
num+=1
print('1-100间数字累加和为{0},偶数累加和为{1},奇数累加和为{2}'.format(sum_total,sum_oushu,sum_jishu))
(6)
sum_total=0
sum_oushu=0
sum_jishu=0
for num in range(1,101):
sum_total+=num
if num%2==0:
sum_oushu += num
else:
sum_jishu += num
print('1-100间数字累加和为{0},偶数累加和为{1},奇数累加和为{2}'.format(sum_total,sum_oushu,sum_jishu))
(7)
for m in range(5):
for n in range(5):
print(m,end='\t')
print()
(8)略(9)
r1=dict(姓名='高小一',年龄=18,薪资=30000,城市='北京')
r2=dict(姓名='高小二',年龄=19,薪资=20000,城市='上海')
r3=dict(姓名='高小五',年龄=20,薪资=10000,城市='深圳')
d=[r1,r2,r3]
for n in d:
if n.get('薪资')>15000:
print(n)
(10)
salary=[]
sum_salary=0
num=0
while True:
x=input('请输入员工薪资:')
if x.upper()=='Q':
break
elif float(x)<0:
print('输入有误!')
continue
else:
num+=1
sum_salary+=float(x)
salary.append(x)
print('已录入薪资的员工数量为{0},平均薪资为{1}'.format(num,sum_salary/num))
print('薪资明细如下:')
for a in salary:
print(a)
(11)
salarySum= 0
salarys = []
for i in range(4):
s = input("请输入一共4名员工的薪资(按 Q或 q中途结束)")
if s.upper()=='Q':
print("录入完成,退出")
break
if float(s)<0:
continue
salarys.append(float(s))
salarySum += float(s)
else:
print("您已经全部录入4 名员工的薪资")
print("录入薪资:",salarys)
print("平均薪资{0}".format(salarySum/4))
(12)
import turtle
turtle.speed(2)
turtle.width(5)
turtle_color=['red','orange','yellow','green'\
,'blue','purple']
for n in range(9):
turtle.color(turtle_color[n%6])
turtle.pendown()
turtle.circle(20+n*10)
turtle.penup()
turtle.goto(0,-10-10*n)
turtle.done()
(13)
import turtle
t=turtle.Pen()
for i in range(19):
t.penup()
t.goto(-180,180-20*i)
t.pendown()
t.goto(180,180-20*i)
for j in range(19):
t.penup()
t.goto(-180+20*j, 180)
t.pendown()
t.goto(-180+20*j,-180)
turtle.done()