随笔 20190804 Python解题记录第7题
许灼灼 记录于20190804
题目来源:菜鸟教程
题目序号:7
题目描述:将一个列表的数据复制到另一个列表中。
这道题的关键词有两个:列表、复制
关于列表:
列表是Python中最常见的一种数据结构,特点是有序,符号是[],并且在列表中的元素可以是其他数据结构,比如列表中的元素可以是列表
关于复制(拷贝):
复制包含赋值、浅拷贝和深拷贝
【开始解题】
这是一道没有给任何变量的题目,因此列表的名字可以自定义,我给源列表命名为a,目的列表命名为b。
先定义两个自定义函数,以供后面调用
# 显示列表a,b的值
defshowab(a,b):
print("当前的a和b的值:")
print(a)
print(b)
# 显示列表a,b的内存地址值
defshowid(a,b):
print("当前的a和b的内存地址值:")
print(id(a)) # 显示a的内存地址
print(id(b)) # 显示b的内存地址
【赋值】
所谓赋值,就是将等号右边的值赋值给等到左边的值,代码如下:
a = [1, 2, 3] # 定义列表a,并赋初值
b = a # 定义变量b,并将a的值赋值给b
showab(a,b) # 调用函数,显示a,b的值
a.append(4) # 给a增加值
showab(a,b) # 调用函数,显示a,b的值
b.remove(2) # 删除b里面的值
showab(a,b) # 调用函数,显示a,b的值
showid(a,b) # 调用函数,显示a,b的内存地址
运行结果:
当前的a和b的值:
[1, 2, 3]
[1, 2, 3]
当前的a和b的值:
[1, 2, 3, 4]
[1, 2, 3, 4]
当前的a和b的值:
[1, 3, 4]
[1, 3, 4]
当前的a和b的内存地址值:
2510384882248
2510384882248
赋值可以将1个值给与另外1个值,但两者的本质是相同的,当改变其中一个值的时候,另外一个值也会改变
举个例子:就像西游记里面的孙悟空和金角大王打斗的时候,孙行者,行者孙,者行孙是同一个道理
Id相同,所以这不算复制,但可以叫关联
【浅复制】
浅复制的第一种方式是切片复制
a=[1,2,3]
b=a[:]
showab(a,b) # 调用函数,显示a,b的值
a.append(4) # 给a增加值
showab(a,b) # 调用函数,显示a,b的值
b.remove(2) # 删除b里面的值
showab(a,b) # 调用函数,显示a,b的值
showid(a,b) # 调用函数,显示a,b的内存地址
运行结果
当前的a和b的值:
[1, 2, 3]
[1, 2, 3]
当前的a和b的值:
[1, 2, 3, 4]
[1, 2, 3]
当前的a和b的值:
[1, 2, 3, 4]
[1, 3]
当前的a和b的内存地址值:
2510386803272
2510385373000
两者id不同,可以称之为复制
切片复制可以达到两者之间的分离,各顾各的,当改变其中一个变量的时候,另外一个变量不受影响
但是当列表里面的元素也是列表的时候,改变内部元素内的列表值的时候,切片复制就无法做到两者分离了
如下代码所示:
a=[1,2,['x','y','z'],3]
b=a[:]
showab(a,b) # 调用函数,显示a,b的值
a.append(4) # 给a增加值
showab(a,b) # 调用函数,显示a,b的值
b.remove(2) # 删除b里面的值
showab(a,b) # 调用函数,显示a,b的值
showid(a,b) # 调用函数,显示a,b的内存地址
a[2].append('n')
showab(a,b) # 调用函数,显示a,b的值
运行结果:
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3]
[1, 2, ['x', 'y', 'z'], 3]
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3, 4]
[1, 2, ['x', 'y', 'z'], 3]
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3, 4]
[1, ['x', 'y', 'z'], 3]
当前的a和b的内存地址值:
2510386699592
2510386803272
当前的a和b的值:
[1, 2, ['x', 'y', 'z', 'n'], 3, 4]
[1, ['x', 'y', 'z', 'n'], 3]
可以清楚的看到列表内的['x', 'y', 'z', 'n']都同步改变了
【深复制】
那如何做到即便是列表内的元素也是列表,在复制之后,也是分离的呢,这里要引入一个copy库,在copy库中,有copy函数和deepcopy函数
print(dir(copy)) # 看看有哪些函数
# help(copy.deepcopy) # copy库中copy函数怎么使用
copy函数的效果和切片复制的效果相同,代码如下
# 浅复制,拷贝
importcopy
print(dir(copy)) # 看看有哪些函数
help(copy.copy) # copy库中copy函数怎么使用
a=[1,2,['x','y','z'],3]
b=copy.copy(a)
showab(a,b) # 调用函数,显示a,b的值
a.append(4) # 给a增加值
showab(a,b) # 调用函数,显示a,b的值
b.remove(2) # 删除b里面的值
showab(a,b) # 调用函数,显示a,b的值
showid(a,b) # 调用函数,显示a,b的内存地址
a[2].append('n')
showab(a,b) # 调用函数,显示a,b的值
运行结果
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3]
[1, 2, ['x', 'y', 'z'], 3]
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3, 4]
[1, 2, ['x', 'y', 'z'], 3]
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3, 4]
[1, ['x', 'y', 'z'], 3]
当前的a和b的内存地址值:
2876225428872
2876225528456
当前的a和b的值:
[1, 2, ['x', 'y', 'z', 'n'], 3, 4]
[1, ['x', 'y', 'z', 'n'], 3]
而deepcopy则就是深拷贝了,它能够实现两个变量的彻底分离,代码如下:
importcopy
a=[1,2,['x','y','z'],3]
b=copy.deepcopy(a)
showab(a,b) # 调用函数,显示a,b的值
a.append(4) # 给a增加值
showab(a,b) # 调用函数,显示a,b的值
b.remove(2) # 删除b里面的值
showab(a,b) # 调用函数,显示a,b的值
showid(a,b) # 调用函数,显示a,b的内存地址
a[2].append('n')
showab(a,b) # 调用函数,显示a,b的值
运行结果:
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3]
[1, 2, ['x', 'y', 'z'], 3]
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3, 4]
[1, 2, ['x', 'y', 'z'], 3]
当前的a和b的值:
[1, 2, ['x', 'y', 'z'], 3, 4]
[1, ['x', 'y', 'z'], 3]
当前的a和b的内存地址值:
2876223611464
2876228529096
当前的a和b的值:
[1, 2, ['x', 'y', 'z', 'n'], 3, 4]
[1, ['x', 'y', 'z'], 3]
总结,关于复制(拷贝)
第一,要分清楚赋值和复制的差别
第二,要分清楚浅复制和深复制的差别
1、赋值操作:=(两者藕断丝连)
2、复制操作
2.1 浅复制:切片复制、copy库中的copy函数(两者段打断骨头连着筋)
2.2 深复制:copy库中的deepcopy函数(两者老死不相往来)
【打油诗】
关于复制那点事,得分赋值和复制
赋值看着像复制,其实藕断还丝连
复制又分浅和深,两者区别很分明
先说浅复有两种,切片以及copy库
浅复复制不彻底,打断骨头连着筋
要想老死不往来,还得看咱深复制
deepcopy,deepcopy,deepcopy!
【写在最后】
解答本题,需要掌握 1、赋值运算符 2、切片 3、copy库 4、id函数
当然,判断两者是否相同,除了可以用id函数看内存地址,也可以用is运算符来进行比较
【展示下一题】
题目序号:8
题目描述:输出 9*9 乘法口诀表。