Python笔记 Day4

内容概要

  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, [...]]

猜你喜欢

转载自www.cnblogs.com/double-W/p/9425499.html