内容概要
1、for循环原理
2、set集合
3、深浅拷贝
主要内容:
一、for循环原理
先看以下示例:
li = [11, 22, 33, 44] for e in li: li.remove(e) print(li) # 结果: [22, 44]
分析原因: for的运行过程,会有一个指针来记录当前循环的元素是哪一个,一开始这个指针指向第0个,然后获取到0个与那素,紧接着删除第0个。这个时候,原来的第一个元素会自动的往前补一个,变成第0个,然而指针会向后移动一次,指向现在的第一个,所以原来的第一个巧妙的躲过了!(本质上来说,for循环只是进行 索每次增加一的操作)
# 看看for的其他操作 li = [11, 22, 33, 44] for i in range(0, len(li)): del li[i] print(li) # 结果: 报错! 原因:i = 0,1,2 当i=2是此时列表里只有两个数,索引最大才是1 #试试 pop() for el in li: li.pop(el) print(li) # 结果还是[11,22] 始终每次删除指针和位置缩进会导致错位的发生 # 以下两种才是正解: for i in range(0, len(li): li.pop() # 让每一次删除的位置变化都记录下来 print(li) # 或则用以下方法: del_li = [] for e in li : dei_li.append(e) for e in del_li: li.remove(e) # 来一个隔山打牛 print(li)
补充知识点:
dic中的元素在迭代的过程中是不允许进行删除的
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,进行删除 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)
集合 ---> 列表 set(list)
转换成False的数据:0,'',None,[],{},(),set()
print(bool(set()))
print(bool({}))
二 、set集合
set集合是python的⼀一个基本数据类型. ⼀一般不是很常⽤用. set中的元素是不重复的(去重).⽆无序的(没有固定的索引).⾥里里 ⾯面的元素必须是可hash的(int, str, tuple,bool), 我们可以这样来记. set就是dict类型的数据但 是不保存value, 只保存key. set也⽤用{}表示
数据类型的总结:
按存值个数区分
标量/原子类型 | 数字,字符串 |
容器类型 | 列表,元组,字典 |
按可变不可变区分
可变 | 列表,字典 |
不可变 | 数字,字符串,元组 |
按访问顺序区分
直接访问 | 数字 |
顺序访问(序列类型) | 字符串,列表,元组 |
key值访问(映射类型) | 字典 |
1、集合的去重:
s = {'王立’ ,'王立','小珠'} print(s) # 一定要区分集合和字典,字典是有键值对,而集合没有键值对! # 利用去重的特性我们可以讲一个含有重复数据的列表去重: set(list) # 注意: set集合中的元素必须是可hash的(也就是不可变元素),否则会报错!但是集合本身是可hash的 ! set = {'1', 'wangli', True, [1, 2, 3]} # 报错 set_1 = {'2', 'xiaozhu', (1, 2, [2, 3, 4]) #同样会报错
2、集合的增删改查:
2.1、增加:
s = {"刘嘉玲", '关之琳', "王祖贤"} s.add("郑裕玲") print(s) s.add("郑裕玲") # 重复的内容不不会被添加到set集合中 print(s) # {'李若彤', '麻', '张曼⽟', '藤', '花', '王祖贤', '刘嘉玲', '关之琳'} s = {"刘嘉玲", '关之琳', "王祖贤"} s.update("麻花藤") # 迭代更更新 print(s) # {'李若彤', '麻', '张曼⽟', '藤', '花', '王祖贤', '刘嘉玲', '关之琳'} s.update(["张曼⽟玉", "李李若彤","李李若彤"]) # 在列表里的也是迭代添加进去 print(s) # {'李若彤', '麻', '张曼⽟', '藤', '花', '王祖贤', '刘嘉玲', '关之琳'}
2.2、删除:
s = {"刘嘉玲", '关之琳', "王祖贤","张曼玉", "李若彤"} item = s.pop() # 随机弹出一个. print(s) print(item) s.remove("关之琳") # 直接删除元素 # s.remove("马⻁疼") # 不存在这个元素. 删除会报错 print(s) s.clear() # 清空set集合.需要注意的是set集合如果是空的. 打印出来是set() 因为要和 dict区分的. print(s) # set()
2.3、修改:
# set集合中的数据没有索引. 也没有办法去定位⼀一个元素. 所以没有办法进⾏行行直接修改. # 我们可以采⽤用先删除后添加的⽅方式来完成修改操作 s = {"刘嘉玲", '关之琳', "王祖贤","张曼⽟玉", "李李若彤"} # 把刘嘉玲改成赵本⼭山 s.remove("刘嘉玲") s.add("赵本⼭山") print(s)
2.4、查找:依旧遍历(没有索引)
# set是⼀一个可迭代对象. 所以可以进⾏行行for循环 for el in s: print(el)
2.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) # {frozenset({'刘能', '赵本山', '皮⻓山', '长跪'}): '123'} 使其可以作键
三、深浅拷贝:lst1 = ["何炅", "杜海涛","周渝民"]
lst2 = lst1.copy() lst1.append("李嘉诚") print(lst1) print(lst2) print(id(lst1), id(lst2)) lst1 = ["何炅", "杜海涛","周渝民", ["麻花藤", "马芸", "周笔畅"]] lst2 = lst1.copy() lst1[3].append("无敌是多磨寂寞") print(lst1) print(lst2) print(id(lst1[3]), id(lst2[3])) ''' 运行结果: ['何炅', '杜海涛', '周渝民', '李嘉诚'] ['何炅', '杜海涛', '周渝民'] 2679402030856 2679401042568 ['何炅', '杜海涛', '周渝民', ['麻花藤', '⻢马芸', '周笔畅', '无敌是多磨寂寞']] ['何炅', '杜海涛', '周渝民', ['麻花藤', '⻢马芸', '周笔畅', '无敌是多磨寂寞']] 2679401060744 2679401060744 ''' 浅拷贝:数据半共享(复制其数据独立内存存放,但是只拷贝成功第一层) 但是第一层虽然拷贝了,但是可以直接修改,在第一层中如果存在嵌套地址,那么修改嵌套里面的数据,大家都会改: lst1 = ["何炅", "杜海涛","周渝民", ["麻花藤", "马芸",[2,3],"周笔畅"]] lst2 = lst1.copy() lst1[3].append("无敌是多磨寂寞") lst1[3][2].append('hahah') print(lst1) print(lst2) #['何炅', '杜海涛', '周渝民', ['麻花藤', '马芸', [2, 3, 'hahah'], '周笔畅', '无敌是多磨寂寞']] ['何炅', '杜海涛', '周渝民', ['麻花藤', '马芸', [2, 3, 'hahah'], '周笔畅', '无敌是多磨寂寞']] 深拷贝:数据完全不共享(复制其数据完完全全放独立的一个内存,完全拷贝,数据不共享)深拷贝就是完完全全复制了一份,且数据不会互相影响,因为内存不共享。 import copy l1 = [1, 2, 3, [11, 22, 33]] # l2 = copy.copy(l1) 浅拷贝 l2 = copy.deepcopy(l1) print(l1,'>>>',l2) l2[3][0] = 1111 print(l1,">>>",l2)
补充个面试题:
a = [1, 2]
a[1] = a
print(a) # 结果: [1, [...]]