今日温故知新内容
python底层数据存放知识延伸——数据的深拷贝和浅拷贝
有如下需求,通过复制一个列表得到另一个列表,对其中一个列表进行任意的改操作,完全不会影响到另一个列表,也就是说复制得到的列表是完全独立的
首先,我们试下如下操作:
list01 = [\'tom\',\'susan\',[11,22]]
list02 = list01
list01[2][0] = 111
list02[2][1] = 222
print(list01)
#[\'tom\', \'susan\', [111, 222]]
print(list02)
#[\'tom\', \'susan\', [111, 222]]
上面的操作,其实就是变量的赋值,和拷贝半毛钱关系都没有;
list02 = list01本质上就是在内存栈区将变量名list01与列表[\'tom\',\'susan\',[11,22]]内存地址的对应关系复制了一份,直接丢给了变量list02,在堆区中没有发生任何事情,又何来拷贝一说,实际过程如下图所示。
list01和list02引用的是堆区中的同一个内存地址,相当于一个人有两个不同的名字。
根据上面的信息来运行python中的copy操作,代码如下:
list01 = [\'tom\',\'susan\',[11,22]]
list02 = list01.copy()
print(id(list01),id(list01[0]),id(list01[1]),id(list01[2]))
#38881792 38856368 38856688 38856064
print(id(list02),id(list02[0]),id(list02[1]),id(list02[2]))
#39511232 38856368 38856688 38856064
list01[0] = \'egon\'
list02[1] = \'alex\'
list01[2][0] = 111
list02[2][1] = 222
print(list01)
#[\'egon\', \'susan\', [111, 222]]
print(list02)
#[\'tom\', \'alex\', [111, 222]]
list02 = list01.copy()是python中的浅拷贝操作;从list02和list01内存地址不一样,可以看出copy操作在堆区中开辟了一个全新的内存空间;而从所有元素的id一模一样可以看出,新的内存空间存的内容与原来的是一模一样的;
对于不可变类型来说,对它进行了直接引用,如果对其修改,必定指向新的内存地址,因此不会影响另外一个列表的值;这一点可以从list01、list02最后的打印结果进行验证。
而对于可变类型(容器类型)来说,对它进行的是间接引用,如果对其修改,只是修改了容器内单个元素指向的内存地址,它本身的内存地址没有发生变化,另外一个列表仍然对它进行了引用,因此另一个列表的值也会发生变化。这一点可以从list01、list02最后的打印结果进行验证。
copy操作并不能实现需求,最后再实验一下deepcopy操作。
import copy
list01 = [\'tom\',\'susan\',[11,22]]
list02 = copy.deepcopy(list01)
print(id(list01),id(list01[0]),id(list01[1]),id(list01[2]))
#39511616 38855920 38856688 39579712
print(id(list02),id(list02[0]),id(list02[1]),id(list02[2]))
#39697408 38855920 38856688 39696768
list01[0] = \'egon\'
list02[1] = \'alex\'
list01[2][0] = 111
list02[2][1] = 222
print(list01)
#[\'egon\', \'susan\', [111, 22]]
print(list02)
#[\'tom\', \'alex\', [11, 222]]
list02 = copy.deepcopy(list01)是python中的深拷贝操作;从list02和list01内存地址不一样,可以看出copy操作在堆区中开辟了一个全新的内存空间;deepcopy将可变和不可变类型进行了区分,把列表中不可变类型元素的内存地址对应关系完整复制了一份,将可变类型元素的索引指向新的内存地址。这样改变操作最终只作用到了不可变类型身上,原列表和拷贝的列表互不影响。
1、while循环的语法与基本使用
print(1)
while 条件:
代码1
代码2
代码3
print(3)
count=0
while count < 5: # 5 < 5
print(count) # 0,1,2,3,4
count+=1 # 5
print(\'顶级代码----->\')
2、死循环与效率问题
count=0
while count < 5: # 5 < 5
print(count) # 0,1,2,3,4
while True:
name=input(\'your name >>>> \')
print(name)
纯计算无io的死讯会导致致命的效率问题
while True:
1+1
while 1:
print(\'xxxx\')
3、循环的应用
两个问题:
1)重复代码
2)输对了应该不用再重复
username = \'egon\'
password = \'123\'
while True:
inp_name=input(\'请输入您的账号:\')
inp_pwd=input(\'请输入您的密码:\')
if inp_name == username and inp_pwd == password:
print(\'登录成功\')
else:
print(\'账号名或密码错误\')
4、退出循环的两种方式
方式一:将条件改为False,等到下次循环判断条件时才会生效
tag=True
while tag:
inp_name=input(\'请输入您的账号:\')
inp_pwd=input(\'请输入您的密码:\')
if inp_name == username and inp_pwd == password:
print(\'登录成功\')
tag = False # 之后的代码还会运行,下次循环判断条件时才生效
else:
print(\'账号名或密码错误\')
# print(\'====end====\')
方式二:break,只要运行到break就会立刻终止本层循环
while True:
inp_name=input(\'请输入您的账号:\')
inp_pwd=input(\'请输入您的密码:\')
if inp_name == username and inp_pwd == password:
print(\'登录成功\')
break # 立刻终止本层循环
else:
print(\'账号名或密码错误\')
# print(\'====end====\')
5、while循环嵌套与结束
\'\'\'
tag=True
while tag:
while tag:
while tag:
tag=False
每一层都必须配一个break
while True:
while True:
while True:
break
break
break
\'\'\'
break的方式
while True:
inp_name=input(\'请输入您的账号:\')
inp_pwd=input(\'请输入您的密码:\')
if inp_name == username and inp_pwd == password:
print(\'登录成功\')
while True:
cmd=input("输入命令>: ")
if cmd == \'q\':
break
print(\'命令{x}正在运行\'.format(x=cmd))
break # 立刻终止本层循环
else:
print(\'账号名或密码错误\')
# print(\'====end====\')
改变条件的方式
tag=True
while tag:
inp_name=input(\'请输入您的账号:\')
inp_pwd=input(\'请输入您的密码:\')
if inp_name == username and inp_pwd == password:
print(\'登录成功\')
while tag:
cmd=input("输入命令>: ")
if cmd == \'q\':
tag=False
else:
print(\'命令{x}正在运行\'.format(x=cmd))
else:
print(\'账号名或密码错误\')
6、while +continue:结束本次循环,直接进入下一次
强调:在continue之后添加同级代码毫无意义,因为永远无法运行
count=0
while count < 6:
if count == 4:
count+=1
continue
# count+=1 # 错误
print(count)
count+=1
7、while +else:针对break
count=0
while count < 6:
if count == 4:
count+=1
continue
print(count)
count+=1
else:
print(\'else包含的代码会在while循环结束后,并且while循环是在没有被break打断的情况下正常结束的,才会运行\')
count=0
while count < 6:
if count == 4:
break
print(count)
count+=1
else:
print(\'======>\')
8、应用案列:
版本1:
count=0
tag=True
while tag:
if count == 3:
print(\'输错三次退出\')
break
inp_name=input(\'请输入您的账号:\')
inp_pwd=input(\'请输入您的密码:\')
if inp_name == username and inp_pwd == password:
print(\'登录成功\')
while tag:
cmd=input("输入命令>: ")
if cmd == \'q\':
tag=False
else:
print(\'命令{x}正在运行\'.format(x=cmd))
else:
print(\'账号名或密码错误\')
count+=1
版本2:优化
count = 0
while count < 3:
inp_name = input(\'请输入您的账号:\')
inp_pwd = input(\'请输入您的密码:\')
if inp_name == username and inp_pwd == password:
print(\'登录成功\')
while True:
cmd = input("输入命令>: ")
if cmd == \'q\': # 整个程序结束,退出所有while循环
break
else:
print(\'命令{x}正在运行\'.format(x=cmd))
break
else:
print(\'账号名或密码错误\')
count += 1
else:
print(\'输错3次,退出\')