第四节
第46课时 字典
字典是“键值对”无序可变序列,字典中的每个元素都是一个“键值对”,包含:“键 对象”和“值对象”。可以通过“键对象”实现快速获取、删除、更新对应的“值对象。列表中我们通过“下标数字”找到对应的对象。字典中通过“键对象”找到对应的“值 对象”。“键”是任意的不可变数据,比如:整数、浮点数、字符串、元组。但是:列表、 字典、集合这些可变对象,不能作为“键”。并且“键”不可重复。 “值”可以是任意的数据,并且可重复
一个典型的字典的定义方式: a ={'name':'gaoqi','age':18,'job':'programmer'}
a.get(name)可以根据 键找到对应的值
第47课时 字典的创建
1. 我们可以通过{}、dict()来创建字典对象。
>>> a={"name":"gaoqi","age":"18","job":"sudent"}#用{}来建立字典
>>> b=dict(name="gaoqi",age=18)#用dict函数来建立字典
>>> c=dict([("name","gaoqi"),("age",18)])#用列表中的元组来建立字典
>>> d={}#空的字典对象
>>> e=dict()#空的字典对象
2.通过zip()创建字典对象
>>> k=["name","age","job"]#键组成的列表
>>> v=["gaoqi",18,"student"]#对象组成的列表
>>> d=dict(zip(k,v))
>>> d
{'name': 'gaoqi', 'age': 18, 'job': 'student'}
3.通过fromkeys来创建值为空的字典
>>> a = dict.fromkeys(['name','age','job'])
>>> a {'name': None, 'age': None, 'job': None}
第48课时 字典元素的访问
设置 a={"name":"gaoqi","age":18,"job":“student”}
1. 通过[键]获得“值”,如果“值”不存在,抛出异常
>>> a=={"name":"gaoqi","age":18,"job":"student"}
False
>>> a={"name":"gaoqi","age":18,"job":"student"}
>>> a["name"]
'gaoqi'
>>> a['age']
18
>>> a['sex']
Traceback (most recent call last):
File "<pyshell#181>", line 1, in <module>
a['sex']
KeyError: 'sex'
>>>
2. 通过get()获得值。推荐使用。原因有二(1)指定键不存在,返回none;(2)当指定建不存在时,还可以修改返回对象none为指定的对象
>>> a.get("name")
'gaoqi'
>>> a.get("sex")
>>> a.get("sex","不存在")#当sex键对应的值不存在时,返回“不存在”字符串
'不存在'
3. 列出所有的键值对
>>> a.items()
dict_items([('name', 'gaoqi'), ('age', 18), ('job', 'student')])
4.列出所有的键(key函数),列出所有的值(value函数)
>>> a.keys()
dict_keys(['name', 'age', 'job'])
>>> a.values()
dict_values(['gaoqi', 18, 'student'])
5. len()键值对个数
>>> len(a)
3
6.检测一个键是否在字典中
>>> "name" in a
True
>>> "gaoqi" in a
False
第49课时 字典元素添加 修改 删除
1. 给字典新增“键值对”,如果键值对存在,就覆盖原有的键值对,如果不存在,则新增键值对
>>> a
{'name': 'gaoqi', 'age': 18, 'job': 'student', 'address': 'linfen', 'sex': 'female'}
>>> a["address"]="linfen"
>>> a["name"]='chuchu'
>>> a
{'name': 'chuchu', 'age': 18, 'job': 'student', 'address': 'linfen', 'sex': 'female'}
2.使用update()可以将字典中所有的键值对全部加到旧字典对象中,key如果重复,就直接覆盖
>>> a
{'name': 'chuchu', 'age': 18, 'job': 'student', 'address': 'linfen', 'sex': 'female'}
>>> b={"name":"yuyingying","money":"1000"}
>>> a.update(b)
>>> a
{'name': 'yuyingying', 'age': 18, 'job': 'student', 'address': 'linfen', 'sex': 'female', 'money': '1000'}
3. 字典元素中的删除,可以用del(),也可以clear()删除所有键值对,或者pop()删除指定键值对并返回对应的“值对象”
>>> del(a["name"])
>>> a
{'age': 18, 'job': 'student', 'address': 'linfen', 'sex': 'female', 'money': '1000'}
>>> b=a.pop(a["age"])
Traceback (most recent call last):
File "<pyshell#203>", line 1, in <module>
b=a.pop(a["age"])
KeyError: 18
>>> b=a.pop("age")#注意pop函数是跟在a.后面的,所以直接接键就可以
>>> b
18
4. popitem():随机删除和返回该键值对。字典是“无序可变序列”,因此没有第一个最后一个元素一说,popitem弹出随机项,
>>> a
{'job': 'student', 'address': 'linfen', 'sex': 'female', 'money': '1000'}
>>> a.popitem()
('money', '1000')
>>> a
{'job': 'student', 'address': 'linfen', 'sex': 'female'}
第50课时 序列解包
序列解包可以用于元祖,列表,字典,可以让我们对多个变量进行赋值,同时把列表,字典和元祖取出到 变量当中。
>>> x,y,z=(20,10,30)
>>> x
20
>>> y
10
>>> x
20
>>> (a,b,c)=(20,30,10)
>>> a
20
>>> b
30
>>> v
['gaoqi', 18, 'student']
>>> c
10
>>> [a,b,c]=[10,20,30]
>>> a
10
>>> b
20
当字典进行序列解包时,默认是对键进行解包;如果对键值对操作,则需要items函数;如果对值操作,则需要values函数。
>>> s={"name":"chuchu","age":18,"job":"student"}
>>> a,b,c=s
>>> a
'name'
>>> b
'age'
>>> c
'job'
>>> a,b,s=s.items()
>>> a
('name', 'chuchu')
>>> b
('age', 18)
>>> s
('job', 'student')
>>> s={"name":"chuchu","age":18,"job":"student"}
>>> a,b,c=s.values()#对值进行操作
>>> a
'chuchu'
第51课时 表格数据使用字典和列表存储
源代码在lesson 50.py
r1={"name":"高小一","age":18,"salary":30000,"city":"beijing"}
r2={"name":"chuchu","age":16,"salary":20000,"city":"beijing"}
r3={"name":"shenhuiqian","age":31,"salary":300000,"city":"Tianjin"}
tb=[r1,r2,r3]
#获得第二行人的薪资
print(tb[1].get("salary"))
#打印表中所有的薪资
for i in range (len(tb)):
print(tb[i].get("salary"))
#打印表的所有数据
for i in range(len(tb)):
print(tb[i].get("name"),tb[i].get("age"),tb[i].get("salary"),tb[i].get("city"))
第52课时 字典核心底层原理(重要)
字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的 每个单元叫做 bucket。每个 bucket 有两部分:一个是键对象的引用,一个是值对象的引 用。 由于,所有 bucket 结构和大小一致,我们可以通过偏移量来读取指定 bucket。而把键和序列对应起来的方法,是通过hash函数,计算键对应的数值,然后用二进制表示,依次和列表序列值对应
将一个键值对放进字典的底层过程
假设字典 a 对象创建完后,数组长度为 8:
我们要把”name”=”gaoqi”这个键值对放到字典对象 a 中,首先第一步需要计算 键”name”的散列值。Python 中可以通过 hash()来计算
由于数组长度为 8,我们可以拿计算出的散列值的最右边 3 位数字作为偏移量,即 “101”,十进制是数字 5。我们查看偏移量 5,对应的 bucket 是否为空。如果为空,则 将键值对放进去。如果不为空,则依次取右边 3 位作为偏移量,即“100”,十进制是数字4。再查看偏移量为 4 的 bucket 是否为空。直到找到为空的 bucket 将键值对放进去。流 程图如下
python 会根据散列表的拥挤程度扩容。“扩容”指的是:创造更大的数组,将原有内容 拷贝到新数组中。 接近 2/3 时,数组就会扩容。
第53课时 根据键查找“键值对”的底层过程
当我们调用 a.get(“name”),就是根据键“name”查找到“键值对”,从而找到值 对象“gaoqi”。 第一步,我们仍然要计算“name”对象的散列值
和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。 假设数组长度为 8,我们可以拿计算出的散列值的最右边 3 位数字作为偏移量,即“101”,十进制是数字 5。我们查看偏移量 5,对应的 bucket 是否为空。如果为空,则返回 None。如果不为空, 则将这个 bucket 的键对象计算对应散列值,和我们的散列值进行比较,如果相等。则将对 应“值对象”返回。如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后, 仍然没有找到。则返回 None。流程图如下
关于字典总结:
1. 键必须可散列 (1) 数字、字符串、元组,都是可散列的。 (2) 自定义对象需要支持下面三点:
2. 字典在内存中开销巨大,典型的空间换时间。
3. 键查询速度很快
4. 往字典里面添加新建可能导致扩容,导致散列表中键的次序变化。因此,不要在遍历字 典的同时进行字典的修改
第54课时 集合
集合是无序可变,元素不能重复。实际上,集合底层是字典实现,集合的所有元素都是字典 中的“键对象”,因此是不能重复的且唯一的
集合创建和删除
1.使用{}创建集合对象(和字典类似),使用add()添加元素
>>> a={3,5,7}
>>> a
{3, 5, 7}
>>> a.add(9)
>>> a
{9, 3, 5, 7}
2.使用set()可以将列表、元祖等可迭代对象转成集合,如果原来数据存在重复数据,则只保留一个,则只保留一个
>>> a=["a","b","c","d"]
>>> b=set(a)
>>> b
{'c', 'a', 'b', 'd'}
3. remove()删除制定元素;clear()清空整个集合
>>> b.remove("a")
>>> b
{'c', 'b', 'd'}
集合相关操作
>>> a={1,3,"chu"}
>>> b={"he",'it','chu'}
>>> a|b#并集
{'chu', 1, 3, 'he', 'it'}
>>> a&b#交集
{'chu'}
>>> a-b#差集
{1, 3}
>>> a.union(b)#并集
{'chu', 1, 3, 'he', 'it'}
>>> a.intersection(b)#交集
{'chu'}
>>> a.difference(b)#差集
{1, 3}
章节实操作业
2. 使用range生成序列:30,40,50,60,70,80,90
>>> list range(30:80:10)
SyntaxError: invalid syntax
>>> list(range(30,80,10))#注意range括号内使用的是逗号而不是冒号
[30, 40, 50, 60, 70]
3. 推导式生成列表: a = [x*2 for x in range(100) if x%9==0],手写出结果。
[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
4.使用二维列表存储表格信息,并画出简单的内存存储示意图:
>>> a=[
["高小二",18,3000,"北京"],
["高小二",19,2000,'上海'],
["高小五",20,1000,"深圳"]
]
>>> a
[['高小二', 18, 3000, '北京'], ['高小二', 19, 2000, '上海'], ['高小五', 20, 1000, '深圳']]
5. 元组和列表有哪些共同点?有哪些不同点?
共同点:都是一种序列,都可以切片和索引,可以使用len,in等函数
不同点:元组不可变,列表用[]建立,元组用()建立;
6. 创建一个字典对象,包含如下信息:支出金额:300.15,支出日期:2018.10.18,支出人:高小七
>>> a={"支出金额":300.15,"支出日期":2018.10.18,"支出人":"高小七"}
SyntaxError: invalid syntax
>>> a={"支出金额":300.15,"支出日期":"2018.10.18","支出人":"高小七"}
>>>
7.使用字典存储行数据,最后将整个表使用列表存储起来。
>>> r1={"姓名":"高小二","年龄":18,"薪资":30000,"城市":"北京"}
>>> r2={"姓名":"高小三","年龄":19,"薪资":20000,"城市":"上海"}
>>> r3={"姓名":"高小五","年龄":20,"薪资":10000,"城市":"深圳"}
>>> tb=list[r1,r2,r3]
Traceback (most recent call last):
File "<pyshell#22>", line 1, in <module>
tb=list[r1,r2,r3]
TypeError: 'type' object is not subscriptable
>>> tb=[r1,r2,r3]
第55课时 控制语句
前面学习的变量、数据类型(整数、浮点数、布尔)、序列(字符串、列表、元组、字 典、集合),可以看做是数据的组织方式。数据可以看做是“砖块”! 流程控制语句是代码的组织方式,可以看做是“混凝土”。 一个完整的程序,离不开“砖块”,也离不开“混凝土”。他们的组合,才能让我们建 立从小到“一个方法”,大到“操作系统”,这样各种各样的“软件”。
PyCharm 开发环境的使用
常见IDE:
1. IDLE 2. PyCharm 3. wingIDE 4. Eclipse 5.
下载与安装
创建项目:creat new project→右键单击项目,new→python file
运行py文件,右键编辑区,run即可
字体或者风格设置 File→Setteing→Editor→Front
第55课时 选择结构
选择结构通过判断条件是否成立,来决定执行哪个分支。选择结构有多种形式,分为:单分 支、双分支、多分支。流程图如下
单分支选择结构表达:
单分支语法形式如下:
if 条件表达式:
语句/语句块
其中:条件表达式:可以是逻辑表达式、关系表达式、算术表达式
语句/语句块:可以是一条语句或者多条语句,多条语句记得对齐一致
举例: num=input("请输入一个数字")#注意输入的不管哪种类型,都默认为字符型,所以后面需要转成整数型 if float(num)<10: print(num)条件
条件表达式详解
在选择和循环结构中,条件表达式的值为 False 的情况如下: False、0、0.0、空值 None、空序列对象(空列表、空元祖、空集合、空字典、空字 符串)、空 range 对象、空迭代对象。
其他情况均为True,这么看来,python所有的合法表达式都可以看做条件表达式,甚至 包括函数调用的表达式。
#测试各种表达式 if 3: #整数表达式 print("ok") a=[] if not a: #测试空列表表达式 print("空列表,False") s="False" if s: #测试字符串表达式 print("非空字符串,True") c=9 if 3<c<20: #测试条件表达式 print("3<c<20") if 3<c and c<20: print("3<c and c<20") if True: #测试布尔型数值表达式 print("True")
执行结果如下:
ok
空列表,False
非空字符串,True
3<c<20
3<c and c<20
True
注意:条件表达式当中,不能有赋值操作符“=”
在 Python 中,条件表达式不能出现赋值操作符“=”,避免了其他语言中经常误将关系运 算符“==”写作赋值运算符“=”带来的困扰。如下代码将会报语法错误:
if 3<c and (c=20): print("赋值符不应该出现在表达式当中")
第56课时 双分支结构
双分支结构的语法格式如下:
if 条件表达式 :
语句 1/语句块 1
else:
语句 2/语句块 2
举例
num=input("请输入一个数字") if float(num)<10: print(num) else: print("数字超出范围")
三元条件运算符
Python 提供了三元运算符,用来在某些简单双分支赋值情况。三元条件运算符语法格式如 下:
条件为真时的值 if (条件表达式) else 条件为假时的值
举例 上一个代码可以写成
print(num if float(num)<10 else "数字太大")
第57课时 多分支结构
多分支结构的算法结构如下:
多分支结构,几个分支之间有逻辑关系,不能随意颠倒
多分支语法格式如下:
if 条件表达式 1 :
语句 1/语句块 1
elif 条件表达式 2:
语句 2/语句块 2
elif 条件表达式 n :
语句 n/语句块 n
[else:
语句 n+1/语句块 n+1
]
【注】计算机行业,描述语法格式时,使用中括号[]通常表示可选,非必选。
举例:输入一个学生成绩,将其转化成简单描述:不及格(<60),及格(0-79),良好(80-89),优秀(90-100)
方法1:(使用完整的条件表达,条件表达式之间的顺序可以替换)
score=float(input("请输入你的分数")) grade="" if score<60: grade="不及格" if 60<=score<80: grade="及格" if 80<=score<90: grade="良好" if 90<=score<=100: grade="优秀" print("分数是{0},等级是{1}".format(score,grade))#占位符的应用
方法2:(利用多分支表达,条件表达式之间有逻辑关系,不能替换)
score=float(input("请输入你的分数")) grade="" if score<60: grade="不及格" elif score<80: grade="及格" elif score<90: grade="良好" else:#可以没有这个结构 grade="优秀" print("分数是{0},等级是{1}".format(score,grade))#占位符的应用选择
第58课时 选择结构嵌套
选择结构可以嵌套,使用时一定要注意控制好不同级别代码块的缩进量,因为缩进量决定了 代码的从属关系。语法格式如下:
if 表达式1:
语句块 1
if 表达式 2:
语句块 2
else:
语句块 3
else:
if 表达式 4:
语句块 4
举例:输入一个分数。分数在 0-100 之间。90 以上是 A,80 以上是 B,70 以上是 C,60 以上是 D。60 以下是 E
#方法一 用条件格式嵌套结构 score=int(input("请输入您的分数")) grade="" if score>100 or score<0: score=int(input("输入错误!请重新输入")) else: if score>=90: grade="A" elif score>=80: grade="B" elif score>=70: grade="C" elif score>=0: grade="D" else: grade="E" print("分数为{0},等级{1}".format(score,grade)) print("*"*100) #方法二 用代码少一点的方法,字符串的索引 degree="ABCDE" num=0 if score>100 or score<0: score = int(input("输入错误!请重新输入")) else: num=score//10 if num<6: num=5 print("分数是{0},等级{1}".format(score,degree[9-num]))
第59课时 循环结构
循环结构用来重复执行一条或多条语句。表达这样的逻辑:如果符合条件,则反 复执行循环体里的语句。在每次执行完后都会判断一次条件是否为 True,如果 为 True 则重复执行循环体里的语句。图示如下:
循环体里面的语句至少应该包含改变条件表达式的语句,以使循环趋于结束;否 则,就会变成一个死循环。
while循环
while 循环的语法格式如下:
while 条件表达式:
循环体语句
举例1:利用While 循环打印从0-10的数字
num=0 while num<=10: print(num) num+=1
举例2:利用While 循环,计算1-100之间的数字累加和,计算 1-100 之间偶数的累加和, 计算 1-100 之间奇数的累加和
num=0 sum_all=0#所有数字的和 sum_even=0#偶数的累加和 sum_odd=0#奇数的累加和 while num<=100: sum_all+=num if num%2==0: sum_even+=num else:sum_odd+=num num+=1#改变条件表达式,使循环趋近于结束 print("1-100所有数的累加和",sum_all) print("1-100所有偶数的累加和",sum_even) print("1-100所有奇数的累加和",sum_odd)