# 本节主要内容:
# 1、基础数据类型补充
# 2、set
# 3、深浅拷贝
#
# 一、基础数据类型补充
# 1、"".join():将列表拼接转化为字符串 与split()相反
# x = ["你是谁", "我是渣渣辉", "我在玩贪玩蓝月", "一起玩哇"]
# y = "_".join(x)
# print(y) # 你是谁_我是渣渣辉_我在玩贪玩蓝月_一起玩哇
# y = "sb".join(x)
# print(y) # 你是谁sb我是渣渣辉sb我在玩贪玩蓝月sb一起玩哇
# x1 = "来玩贪玩蓝月"
# y = "_".join(x1)
# print(y) # 来_玩_贪_玩_蓝_月
# 列表:
# 循环删除列表中的每一个元素:
# li = [11, 22, 33, 44]
# for e in li:
# li.remove(e) # 当你在循环时同时删除li列表时会导致列表中元素重新排序,结果删不干净
# print(li) # [22, 44]
# 不论用remove、还是del、还是pop都不行
# 分析原因:
# for的运⾏过程. 会有一个指针来记录当前循环的元素是哪一个, 一开始这个指针指向第0
# 个. 然后获取到第0个元素. 紧接着删除第0个. 这个时候. 原来是第⼀个的元素会⾃动的变成
# 第0个. 然后指针向后移动⼀次, 指向1元素. 这时原来的1已经变成了0, 也就不会被删除了.
# 只有这样才是可以的:
# for i in range(0, len(li)): # 循环len(li)次, 然后从后往前删除
# li.pop() # 因为pop删除是删除列表中的最后一个元素
# print(li)
# 或者、 用另一个列表来记录你要删除的内容. 然后循环删除
# li = [11, 22, 33, 44]
# del_li = []
# for e in li:
# del_li.append(e)
# for e in del_li:
# li.remove(e)
# print(li) # 这样删除不会导致列表元素顺序改变
# 注意: 由于删除元素会导致元素的索引改变, 所以容易出现问题. 尽量不要再循环中直接去删
# 除元素. 可以把要删除的元素添加到另一个集合中然后再批量删除.
# dict中的fromkeys(),可以帮我们通过list来创建一个新的dict:
# dic = dict.fromkeys(["jay","JJ"]), ["周杰伦","林俊杰"]
# print(dic) # ({'jay': None, 'JJ': None}, ['周杰伦', '林俊杰'])
# 前面列表中的每一项都会作为key,后面列表中的内容作为value,生成新的dict
# d = {}
# d.fromkeys(["jay", "JJ"]), ["周杰伦", "林俊杰"])
# y = d.fromkeys(["jay", "JJ"], ["周杰伦", "林俊杰"])
# print(d) # 输出结果 {} 因为fromkeys会生成新列表对原列表无影响
# print(y) # ({'jay': None, 'JJ': None}, ['周杰伦', '林俊杰']) 生成新字典
# d = dict.fromkeys(["jay", "JJ"], ["周杰伦", "林俊杰"])
# d.get("jay").append("杨千嬅")
# print(d) # {'jay': ['周杰伦', '林俊杰', '杨千嬅'], 'JJ': ['周杰伦', '林俊杰', '杨千嬅']}
# 因为jay 和 jj对应的value是同一个列表,当列表发生改变自然都会改变
# 代码中只是更改了jay那个列表. 但是由于jay和JJ用的是同一个列表. 所以. 前面那个改了. 后
# 面那个也会跟着改
# dict中的元素在迭代过程中是不允许进行删除的
# dic = {'k1': 'alex', 'k2': 'wusir', 's1': '金老板'}
# # 删除key中带有'k'的元素
# for k in dic:
# if 'k' in k:
# del dic[k]
# dictionary changed size during iteration, 在循环迭代的时候不允许进⾏删除操作
# print(dic)
# 当在循环字典时删除字典会导致字典长度改变导致报错
# 那怎么办呢? 把要删除的元素暂时先保存在⼀个list中, 然后循环list, 再删除
# dic = {'k1': 'alex', 'k2': 'wusir', 's1': '⾦⽼板'}
# dic_del_list = []
# # 删除key中带有'k'的元素
# for k in dic:
# if 'k' in k:
# dic_del_list.append(k)
# for el in dic_del_list:
# del dic[el]
# print(dic)
# 类型转换:
# 元组 => 列表 list(tuple)
# 列表 => 元组 tuple(list)
# list=>str str.join(list)
# str=>list str.split()
# 转换成False的数据:
# 0,'',None,[],(),{},set() ==> False
# 二. set集合
# set集合是python的一个基本数据类型. 一般不是很常用. set中的元素是不重复的.无序的.里
# 面的元素必须是可hash的(int, str, tuple,bool), 我们可以这样来记. set就是dict类型的数据但
# 是不保存value, 只保存key. set也用{}表示
# 注意: set集合中的元素必须是可hash的, 但是set本身是不可hash得. set是可变的.
# set集合里面的元素是不能变的,但是set集合本身可以做增、删、改、查
# 增加:
# s = {"刘嘉玲", '关之琳', "王祖贤"}
# # s.add("郑裕玲")
# # print(s)
# s.add("关之琳")
# 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()
# set()集合没有del 这种删除方式
# 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.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'} # 可以正常使⽤了 frozenset之后s为不可变值,可以用作key
# print(dic)
# x = ["赵本山", "刘能", "皮长山", "长跪"]
# y = frozenset(["赵本山", "刘能", "皮长山", "⻓跪"])
# print(y) # frozenset({'皮长山', '⻓跪', '刘能', '赵本山'})
# 二、深浅拷贝
# 赋值(=)
# lst1 = ["金毛狮王", "紫衫龙王", "白眉鹰王", "青翼蝠王"]
# lst2 = lst1
# print(lst1)
# print(lst2)
# lst1.append("杨逍")
# print(lst1) # ['金毛狮王', '紫衫龙王', '白眉鹰王', '青翼蝠王', '杨逍']
# print(lst2) # ['⾦⽑狮王', '紫衫⻰王', '⽩眉鹰王', '⻘翼蝠王', '杨逍']
#
# dic1 = {"id": 123, "name": "谢逊"}
# dic2 = dic1
# print(dic1) # {'id': 123, 'name': '谢逊'}
# print(dic2) # {'id': 123, 'name': '谢逊'}
# dic1['name'] = "范瑶"
# print(dic1) # {'id': 123, 'name': '范瑶'}
# print(dic2) # {'id': 123, 'name': '范瑶'}
# 赋值两个列表、字典指向的是同一个内存地址所以当有一个改变另一个也会跟着改变
# 对于list, set, dict来说, 直接赋值. 其实是把内存地址交给变量. 并不是复制⼀份内容. 所以.
# lst1的内存指向和lst2是⼀样的. lst1改变了, lst2也发⽣了改变
# 浅拷贝:
# lst1 = ["何炅", "杜海涛", "周渝⺠"]
# lst2 = lst1.copy()
# print(lst1) # ['何炅', '杜海涛', '周渝⺠']
# print(lst2) # ['何炅', '杜海涛', '周渝⺠']
# print(id(lst1), id(lst2)) # 13841832 13842992 copy浅拷贝是直接开辟一个新的内存空间给lst2,两个内存地址不同,无相关性
# lst1.append("pig")
# print(lst1) # ['何炅', '杜海涛', '周渝⺠', 'pig']
# print(lst2) # ['何炅', '杜海涛', '周渝⺠']
# print(id(lst1), id(lst2)) # 16135592 16136752 copy浅拷贝是直接开辟一个新的内存空间给lst2,两个内存地址不同,无相关性,lst1改变对lst2无影响
# lst1 = ["何炅", "杜海涛","周渝⺠", ["麻花藤", "⻢芸", "周笔畅"]]
# lst2 = lst1.copy()
# lst1[3].append("⽆敌是多磨寂寞")
# print(lst1) # ['何炅', '杜海涛', '周渝⺠', ['麻花藤', '⻢芸', '周笔畅', '⽆敌是多磨寂寞']]
# print(lst2) # ['何炅', '杜海涛', '周渝⺠', ['麻花藤', '⻢芸', '周笔畅', '⽆敌是多磨寂寞']]
# print(id(lst1), id(lst2)) # 29375024 29738888
# print(id(lst1[3]), id(lst2[3])) # 4417248328 4417248328
# 浅拷贝:lst1、lst2内存地址不一样,但当列表里面嵌套的列表发生改变lst2也会改变因为嵌套的列表在copy中直接copy嵌套内列表的内存编码
# 所以当内存嵌套的列表改变时lst2中嵌套列表也会跟着改变,因为他们嵌套列表是同一个内存地址(同一个列表)
# 浅拷⻉. 只会拷⻉第⼀层. 第⼆层的内容不会拷⻉. 所以被称为浅拷⻉
# 深拷贝
# import copy
# lst1 = ["何炅", "杜海涛", "周渝⺠", ["麻花藤", "⻢芸", "周笔畅"]]
# lst2 = copy.deepcopy(lst1)
# # print(lst1) # ['何炅', '杜海涛', '周渝⺠', ['麻花藤', '⻢芸', '周笔畅']]
# # print(lst2) # ['何炅', '杜海涛', '周渝⺠', ['麻花藤', '⻢芸', '周笔畅']]
# # print(id(lst1), id(lst2)) # 20266720 20266840
# lst1[3].append("无敌是sb")
# print(lst1) # ['何炅', '杜海涛', '周渝⺠', ['麻花藤', '⻢芸', '周笔畅', '无敌是sb']]
# print(lst2) # ['何炅', '杜海涛', '周渝⺠', ['麻花藤', '⻢芸', '周笔畅']]
# print(id(lst1), id(lst2)) # 59129688 59129808
# print(id(lst1[3]), id(lst2[3])) # 48325376 48794400
# 深拷贝:lst1、lst2内存地址不一样,且lst1里面嵌套的列表也直接复制了,相当于lt1、lst2中完全不同,且里面嵌套的元素也是完全独立的
# 所以当lst1改变时lst2没有发生变化。
# 总结深浅拷贝:
# 浅拷贝:只是拷贝第一层的东西第二层第三层是不会被拷贝是直接拿相同的东西去用,拷贝的层次浅
# 深拷贝:拷贝所有东西包括里面嵌套的元素、拷贝成完全独立的两个个体,拷贝层次深
# 深浅拷贝优缺点:
# 浅拷贝:
# 优点: 省内存.
# 缺点: 容易出现同一个对象被多个变量所引用
# 深拷贝
# 有点: 完全拷贝出一份两个对象之间除了数据相同。 没有任何关系
# 缺点: 占内存
⽪⻓⼭