字典,集合
昨日回顾
1. list列表 写法:[元素, 元素] 对元素的数据类型没有要求 也有索引和切片 索引从0开始 切片 lst[start: end: step] 从start到end. 每隔step取一个 增删改查 1. 增加: 1. append() 追加. 在列表的末尾添加 2. insert(index, 元素) 在index位置插入元素 2. 删除: 1. pop(i) 默认从末尾删除, 还可以指定位置删除 ##返回删除的元素 2. remove(元素) 删除指定元素 3. 修改: 通过索引去修改元素 lst[3] = "胡辣汤" 4. 查询: for item in lst: # 拿不到索引 print(item) for i in range(len(lst)):##能拿到索引,当需要输出索引或者需要对原来的列表进行修改的时候(对原列表的修改一定要使用索引) print(i,lst[i]) range(m) 从0到m range(m, n) 从m到n range(m, n, p) 从m到n. 每P个取一个 for i in range(len(lst)): i 索引 lst[i] 元素 元组: 不可变的. 只读列表. 有索引. 有下标, 有切片. 不可变: 内部指向 可变的: list 不可变的:str, int, bool, tuple
今日内容
1. 什么是字典 字典是以key:value的形式来保存数据 用{}表示. 存储的是key:value 2. 字典的增删改查(重点) 1. 添加 dic[新key] = 值 setdefault(key,value) key不存在,添加键值对 2. 删除 pop(key) 删除指定键的键值对, #返回删除的键对应的值 ## dic.popitem() # 随机删除一项(现在的版本一般是弹出最后一项) ##del dic["李安"] ##dic.clear() # 清空 3. 修改 dic[老key] = (新)值 update() 更新字典(迭代更新,类似于列表的 extend) 4. 查询 dic[key] ##直接使用key就可以拿到value get(key, 值) ##当key不存在. 返回第二个参数. 默认第二个参数是None setdefault(key, value) key存在,返回对应的 value,key 不存在,先新增,再返回对应的 value 5. 遍历,字典是一个可迭代对象 3. 字典的相关操作 1. keys() 获取到所有的键 2. values() 获取到所有的值 3. items() 拿到所有的键值对 4. 字典的嵌套 字典的嵌套. 字典套字典 5. 集合(不重要). 去重复(##但是无序) 集合中的元素是不重复的,必须是可哈希的(不可变), 相当于字典中的key(集合本身是可变的,但是它要求它内部的值是不可变的) 空集合:set() 空元组:tuple() 空列表:list() 非空集合: {123}集合, 集合其实就是不存value的字典(字典也是可变的,但是它要求他内部的 key 是不可变的) 预习: 深浅拷贝 小数据池 文件操作(带来的作业) 函数 # 关于set集合作业: 写一个彩票开奖(36选7) from random import randint randint(1,36)
字典
1. 字典的简单介绍
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
lst = ["周杰伦", "林俊杰", "蔡依林"] lst[0] = "麻花藤" # 相比列表,字典查找的效率比较高 # 坑: 字典存储数据的时候是用的hash值来存储. 哈希是一个算法,不能变的(python内置的) # 数据必须是不可变的(可哈希). 字典的key必须是可哈希的(不可变). dic = {"jay":"周杰伦", "jj": "林俊杰", "jolin":"蔡依林"} print(dic['jay']) # 周杰伦 dic['jay'] = "麻花藤" print(type(dic)) # <class 'dict'> # 列表是可变的. 不可哈希 # 元组是不可变的. 可哈希的 print(hash((1,2,3))) print(hash([1,2,3])) # TypeError: unhashable type: 'list' dic = {"jay":"周杰伦", "王力宏":["龙的传人", "唯一", "改变自己"], ["战狼", "战狼2"]: "武警"} print(dic)
字典(dict)是python中唯一的一个映射类型.他是以{ }括起来的键值对组成. 在dict中key是唯一的. 在保存的时候, 根据key来计算出一个内存地址. 然后将key-value保存在这个地址中. 这种算法被称为hash算法, 所以, 切记, 在dict中存储的key-value中的key'必须是可hash的,
如果你搞不懂什么是可哈希, 暂时可以这样记, 可以改变的都是不可哈希的, 那么可哈希就意味着不可变. 这个是为了能准确的计算内存地址而规定的.
已知的可哈希(不可变)的数据类型: int, str, tuple, bool
不可哈希(可变)的数据类型: list, dict, set
#语法 : {key1: value1, key2: value2....}
注意: key必须是不可变(可哈希)的. value没有要求.可以保存任意类型的数据
# 合法 dic = {123: 456, True: 999, "id": 1, "name": 'sylar', "age": 18, "stu": ['帅 哥', '美女'], (1, 2, 3): '麻花藤'} print(dic[123]) print(dic[True]) print(dic['id']) print(dic['stu']) print(dic[(1, 2, 3)]) # 不合法 dic = {[1, 2, 3]: '周杰伦'} # list是可变的. 不能作为key dic = {{1: 2}: "哈哈哈"} # dict是可变的. 不能作为key dic = {{1, 2, 3}: '呵呵呵'} # set是可变的, 不能作为key
dict保存的数据不是按照我们添加进去的顺序保存的. 是按照hash表的顺序保存的. 而hash表不是连续的. 所以不能进⾏切片工作. 它只能通过key来获取dict中的数据
2. 字典增删改查和其他操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
dic = {"意大利": "李云龙", "美国": "美国往事"} # 增 dic["日本"] = "东京审判" # 新key表示添加 dic['韩国'] = "釜山行" # setdefault (难点) # 有添加的功能,如果key是存在的. 不添加 # 流程: 判断你给的key是否在字典中存在了.如果已经存在了. 就不再新增. 如果不存在. 执行新增操作 dic.setdefault("美国", "三傻大闹宝莱坞") print(dic) # 删 dic = {"张艺谋":"红高粱", "李安":"断臂山", "陈凯歌":"霸王别姬", "郭德纲":"祖宗十九代"} dic.pop("郭德纲") # 你要记住的 print('>>>>>',dic.pop("郭德纲")) # >>>>> 祖宗十九代 # dic.popitem() # 随机删除一项. 在python早期版本 字典是无序的.##现在是有序的(输出在屏幕上的显示是有序的,底层还是无序的),所以一般删除的是最后一项 del dic["李安"] dic.clear() # 清空 print(dic) # 改 dic = {"河南":"胡辣汤", "开封": "灌汤包", "武汉":"热干面"} # dic['河南'] = "烩面" # 老key = 新值 print(dic) dic1 = {"赵四":"刘晓光", "刘能":"王晓利", "王木生":"范伟"} dic2 = {"赵四":"宝宝", "刘能":"萌萌", "皮校长":"皮长山"} # 迭代更新 dic1.update(dic2) # 把dic2怼到dic1里面. 把dict2中的内容更新到dic1 print(dic1) print(dic2) # 查 dic1 = {"赵四":"刘晓光", "刘能":"王晓利", "王木生":"范伟"} # 1. 直接使用key就可以拿到value print(dic1["赵四四"]) # KeyError: '赵四四' key不存在 # 2. get(key) print(dic1.get("刘能能")) # None 当key不存在返回None print(dic1.get("刘能能", "没有这个人")) # 当key不存在. 返回第二个参数. 默认第二个参数是None # 3. setdefault() 第一个功能是添加(当key不存在). 第二个功能是查询(根据你给的key查询) # 整个执行流程: 判断给的key是否存在. 如果存在. 就不执行新增流程.直接查询出这个key对应的value # 如果key不存在. 先执行新增操作. 再使用key把对应的value查询出来 ##这里是与 get(key,value)的区别,当 key不存在的时候,get不执行新增操作,直接返回你给定的 value 值,而 setdefault 先执行新增,再执行查询操作 ret = dic1.setdefault("皮长山", "皮校长") print(ret) # 皮校长 ret = dic1.setdefault("王木生", "宝宝") print(ret) # 范伟
1. 增加
dic = {} dic['name'] = '周润发' # 如果dict中没有出现这个key, 就会新增一个key-value的组合进dict dic['age'] = 18 print(dic) # 如果dict中没有出现过这个key-value. 可以通过setdefault设置默认值 dic.setdefault('李嘉诚') # 也可以往⾥面设置值. dic.setdefault("李李嘉诚", "房地产") # 如果dict中已经存在了. 那么setdefault将不会起作⽤ print(dic)
2. 删除
ret = dic.pop("jay") print(ret) del dic["jay"] print(dic) # 随机删除. Python老版本是随机删除,现在就是删除最后一项 ret = dic.popitem() # 清空字典中的所有内容 dic.clear()
3. 修改
dic = {"id": 123, "name": 'sylar', "age": 18} dic1 = {"id": 456, "name": "麻花藤", "ok": "wtf"} dic.update(dic1) # 把dic1中的内容更新到dic中. 如果key重名. 则修改替换. 如果不存在key, 则新增. print(dic) print(dic1)
4. 查询
查询一般是用key来查找具体的数据.
print(dic['name']) # print(dic['sylar']) # 报错 print(dic.get("ok")) print(dic.get("sylar")) # None print(dic.get("sylar", "牛B")) # 牛B # 注意:get(key,value=None):key 不存在返回第二个参数,上面返回的None是默认的
5. 其他相关操作-字典的遍历
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
dic = {"赵四":"刘晓光", "刘能":"王晓利", "王木生":"范伟"} # 直接for循环 for key in dic: # 直接循环字典拿到的是key, 有key直接拿value print(key) print(dic[key]) dic = {"赵四":"刘晓光", "刘能":"王晓利", "王木生":"范伟"} # 不常用的 print(dic.keys()) # dict_keys(['赵四', '刘能', '王木生']) 像列表. 山寨列表 for k in dic.keys(): # 拿到的是字典中的每一个key print(k) # 当需要单独获取到所有value的时候 print(dic.values()) # dict_values(['刘晓光', '王晓利', '范伟']) 所有的value的一个数据集 for v in dic.values(): print(v) print(dic.items()) # 所有的键值对 dict_items([('赵四', '刘晓光'), ('刘能', '王晓利'), ('王木生', '范伟')]) # 遍历字典最简单的方案 for item in dic.items(): # 遍历字典最简单的方案##这里涉及到一个自动解构的过程 print(item) # ('赵四', '刘晓光') k, v = item # 解构,##item 是一个中间变量,可以直接省略掉 k = item[0] v = item[1] for k, v in dic.items(): # 遍历字典最简单的方案##这里涉及到一个自动解构的过程 # k, v = item # 解构,##item 是一个中间变量,可以直接省略掉 print(k, v) a, b = 1, 2 # 把后面的两个值分别赋值给前面两个变量. 解构, 解包 print(a) print(b) ''' 老师课上讲解的总结: ------------------------------------------------------------------------ # a,b = 1,2 #解构必须前后数量相等,不等会报错 # a,b = (1,2) # (a,b) = (1,2)#上面的三种写法是等价的,#元组的括号可以不加,只要有逗号就是元组类型的 # print(a) # print(b) #元组的括号可以不加,只要有逗号就是元组类型的 # a = 1 # print(type(a)) #<class 'int'> # a = 1, # print(type(a)) #<class 'tuple'> # a = (1,) # print(type(a))#<class 'tuple'> ------------------------------------------------------------------------- ''' c = 1,2,3 print(c) # (1, 2, 3) # 元组和列表是可以解包的 d, e, f = [1,2,3] print(d) print(e) print(f) # 遍历字典两套方案(最常用的,需要记忆的) dic = {"赵四":"刘晓光", "刘能":"王晓利", "王木生":"范伟"} # 1. 使用for循环直接遍历字典的key for key in dic: print(key) print(dic[key]) # 2. 可以使用字典的items()+解构可以直接获取到key和value for k, v in dic.items(): print(k) print(v)
dic = {"id": 123, "name": 'sylar', "age": 18, "ok": "科⽐"} print(dic.keys()) # dict_keys(['id', 'name', 'age', 'ok']) 不用管它是什么.当 成list来用就行 for key in dic.keys(): print(key) print(dic.values()) # dict_values([123, 'sylar', 18, '科⽐']) 一样. 也当list来⽤ for value in dic.values(): print(value) print(dic.items()) # dict_items([('id', 123), ('name', 'sylar'), ('age', 18), ('ok', '科⽐比')]) 这个东西也是list. 只不过list中装的是tuple for key, value in dic.items(): # ?? 这个是解构 print(key, value) # 解构 a, b = 1, 2 print(a, b) (c, d) = 3, 4 print(c, d) e, f = [1, 2, 3] # 解构的时候注意数量必须匹配,否则报错 print(e, f)
3. 字典的嵌套
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
wf = { "name":"汪峰", "age":52, "hobby":["唱歌", "上头条", "穿皮裤"], "wife": { "name": "章子怡", "age": 49, "hobby":["演戏", "上电视", "当导师"], "tishen": { "name":"萌萌", "age":28 }, "zhuli":{ "name":"磊磊", "age": 20 } }, "zhuli":{ "name":"宝宝", "age":23, "hobby":["抽烟","喝酒","烫头"] }, "children":[{"name":"汪老大"}, {"name":"汪老二"}] } wf['children'][1]["age"] = 2 print(wf) # print(wf['zhuli']['name']) # 汪峰老婆替身的名字 print(wf['wife']['tishen']['name']) # 汪峰老婆的第二个爱好 print(wf['wife']['hobby'][1]) # 汪峰助理的第三个爱好 print(wf['zhuli']['hobby'][2]) # 汪峰的助理+10岁 wf['zhuli']['age'] = wf['zhuli']['age'] + 10 # 汪峰的老婆添加一个爱好("导戏") wf['wife']['hobby'].append("导戏") # 添加完毕了 # 删除汪峰助理的"抽烟"爱好 wf["zhuli"]["hobby"].remove("抽烟") print(wf)
# 字典的嵌套 dic1 = { "name": "汪峰", "age": 18, "wife": { "name": '章子怡', "age": 28 }, "children": ['第一个毛孩子', '第二个毛孩子'], "desc": '峰哥不会告我吧. 没关系. 我想上头条的' } print(dic1.get("wife").get("name")) print(dic1.get("children")) print(dic1.get("children")[1])
set集合
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
s = {"周润发", "大润发", "王润发", "周润发"} # 不重复的 print(s) # 唯一能用到的点. 去重复(使用强制类型转化的办法:列表-->集合(去除重复的元素)-->列表) lst = ["麻将", "牌九", "骰子", "扑克", "老虎鸡", "骰子", "扑克", "老虎鸡", "扑克", "老虎鸡", "扑克", "老虎鸡"] # 把列表转化成集合 x 转化成y类型 y() s = set(lst) # print(s) # 把集合变回列表 lst = list(s) print(lst) # 顺序是乱的(唯一的缺点,但是功(去重复)大于过.排序和去重复都是相当麻烦的一件事) #增 s = {"刘嘉玲", "赵本山", "莱昂纳多迪卡普里奥", "罗纳尔多"} s.add("刘嘉玲") # 记忆(如果实在是想要记忆的话) print(s) s.update({"刘嘉玲", "刘能", "赵四"}) # 迭代更新 print(s) #删 ret = s.pop() # 随机删除(弹出)一个,类似于字典的popitem() print(s) print(ret) s.remove("罗纳尔多") print(s) # 注意:集合还有字典. 是没有索引和切片的 #改 #set集合中的数据没有索引,也没有办法去定位一个元素,所以没有办法进行直接修改.我们可以采用先删除后添加的方式来完成修改的操作 s = {"刘嘉玲", "赵本山", "莱昂纳多迪卡普里奥", "罗纳尔多"} # 把罗纳尔多修改成梅西 s.remove("罗纳尔多")#先删除 s.add("梅西")#后修改 print(s) #查询 # 迭代 for el in s: print(el) #下面是一些不常使用的操作 s1 = {"门神", "灯神", "灯神你在笑什么?"} s2 = {"门神", "灯神", "你俩在干什么?"} # 交集 print(s1 & s2) print(s1.intersection(s2)) # 并集 print(s1 | s2) print(s1.union(s2)) # 差集 print(s1 - s2) # s1中特有的内容 print(s1.difference(s2)) # 反交集 s1={1,2,3,44} s2={1,2,3,55} print(s1 ^ s2) # 两个集合中特有的内容 {55, 44} print(s1.symmetric_difference(s2)) # 集合本身是可变的数据类型 . 不可哈希 # 集合套集合->不能互相嵌套的 # 集合中的元素必须可哈希(不可变的) s = {{1,2,3}} # TypeError: unhashable type: 'set' print(s) # # 如果非要集合套集合 下面是不可变集合 s = frozenset({"哈哈","呵呵"}) # 不可变的数据类型(集合) for el in s: print(el) s = {s} print(frozenset({"哈哈","呵呵"}))
set集合是python的一个基本数据类型. 一般不是很常用. set中的元素是不重复的.无序的.⾥面的元素必须是可hash的(int, str, tuple,bool), 我们可以这样来记. set就是dict类型的数据但是不保存value, 只保存key. set也用{}表示
注意:set集合中的元素必须是可hash的(不可变),但是set本身是不可hash的(可变的).
set1 = {'1', 'alex',2,True,[1,2,3]} #报错 set2 = {'1', 'alex' ,2,True,{1:2}} # 报错 set3 = {'1', 'alex' ,2,True,(1,2,[2,3,4])}#报错
set中的元素是不重复的,且无序的.
s = {"周杰伦", "周杰伦",”周星星"} print(s) 结果: {'周星星',' 周杰伦'}
使用这个特性,我们可以使用set来去掉重复
#给list去重复 lst = [45,5,"哈哈",45,"哈哈",50] lst = list(set(lst))#把list转换成set, 然后再转换回list print(lst)
set集合增删改查
1.增加
s = {"刘嘉玲",'关之琳',"王祖贤"} s. add( "郑裕玲") print(s) s. add("郑裕玲")#重复的内容不会被添加到set集合中 print(s) s = {"刘嘉玲",'关之琳',"王祖贤"} s. update("麻花藤")#迭代更新 print(s) s. update(["张曼玉”," 李若彤" ,"李若彤"]) print(s)
2. 删除
s = {"刘嘉玲", '关之琳', "王祖贤","张曼玉", "李若彤"} item = s.pop() # 随机弹出一个. print(s) print(item) s.remove("关之琳") # 直接删除元素 # s.remove("⻢虎疼") # 不存在这个元素. 删除会报错 print(s) s.clear() # 清空set集合.需要注意的是set集合如果是空的. 打印出来是set() 因为要和 dict区分的. print(s) # set()
3. 修改
# set集合中的数据没有索引. 也没有办法去定位⼀一个元素. 所以没有办法进⾏直接修改. # 我们可以采⽤先删除后添加的方式来完成修改操作 s = {"刘嘉玲", '关之琳', "王祖贤","张曼玉", "李若彤"} # 把刘嘉玲改成赵本⼭ s.remove("刘嘉玲") s.add("赵本⼭山") print(s)
4. 查询
# set是一个可迭代对象. 所以可以进⾏for循环 for el in s: print(el)
5. 常用操作
s1 = {"刘能", "赵四", "⽪长山"} s2 = {"刘科⻓", "冯乡长", "⽪长山"} # 交集 # 两个集合中的共有元素 print(s1 & s2) # {'⽪长山'} print(s1.intersection(s2)) # {'⽪长山'} # 并集 print(s1 | s2) # {'刘科长', '冯乡长', '赵四', '⽪长山', '刘能'} print(s1.union(s2)) # {'刘科长', '冯乡长', '赵四', '⽪长山', '刘能'} # 差集 print(s1 - s2) # {'赵四', '刘能'} 得到第一个中单独存在的 print(s1.difference(s2)) # {'赵四', '刘能'} # 反交集 print(s1 ^ s2) # 两个集合中单独存在的数据 {'冯乡长', '刘能', '刘科长', '赵四'} print(s1.symmetric_difference(s2)) # {'冯乡长', '刘能', '刘科长', '赵四'} s1 = {"刘能", "赵四"} s2 = {"刘能", "赵四", "⽪长山"} # 子集 print(s1 < s2) # set1是set2的子集吗? True print(s1.issubset(s2)) # 超集 print(s1 > s2) # set1是set2的超集吗? False print(s1.issuperset(s2))
set集合本身是可以发生改变的. 是不可hash的. 我们可以使用frozenset来保存数据. frozenset是不可变的. 也就是一个可哈希的数据类型
s = frozenset(["赵本山", "刘能", "⽪长山", "长跪"]) dic = {s:'123'} # 可以正常使用了 print(dic)
这个不是很常用. 了解一下就可以了