Python深浅拷贝
拷贝(赋值)
当lt2为lt的拷贝对象时,lt内的可变化类型变化,lt2变化;lt内的不可变类型变化,lt2变化
使用的是简单的赋值
lt = [1, 2, 3]
lt2 = lt
lt.append(4)
print(lt)
# 因为列表是可变类型,所以lt的值变化,lt2的值也会跟着变化
print(lt2)
结果为:
[1, 2, 3, 4]
[1, 2, 3, 4]
浅拷贝
使用的是copy.copy()
lt2没有变化的情况
import copy
lt = [1, 2, 3]
lt2 = copy.copy(lt)
lt.append(4)
print(lt) # [1, 2, 3, 4]
print(lt2) # [1, 2, 3]
lt2变化的情况
import copy
lt = [1000, 2000, 3000, [4000, 5000, 6000]]
print('id(lt)', id(lt))
print('id(lt[0])', id(lt[0]))
print('id(lt[1])', id(lt[1]))
print('id(lt[2])', id(lt[2]))
print('id(lt[3])', id(lt[3]))
print('*' * 50)
lt2 = copy.copy(lt)
print('id(lt2)', id(lt2))
print('id(lt2[0])', id(lt2[0]))
print('id(lt2[1])', id(lt2[1]))
print('id(lt2[2])', id(lt2[2]))
print('id(lt2[3])', id(lt2[3]))
结果为:
id(lt) 2913392877192
id(lt[0]) 2913390652080
id(lt[1]) 2913390652048
id(lt[2]) 2913390652272
id(lt[3]) 2913392877256
**************************************************
id(lt2) 2913392875784
id(lt2[0]) 2913390652080
id(lt2[1]) 2913390652048
id(lt2[2]) 2913390652272
id(lt2[3]) 2913392877256
可以发现虽说lt2是lt的复制,并且内存地址不同,但是其内的元素的地址是相同的
之前已经试过,更改lt中的int类型值不会对lt2造成影响,那么列表呢
lt[-1].append(7)
print(lt) # [1, 2, 3, [4, 5, 6, 7]]
print(lt2) # [1, 2, 3, [4, 5, 6, 7]]
lt[0] += 1
print(lt)
print(lt2)
结果为:
[1000, 2000, 3000, [4000, 5000, 6000, 7]]
[1000, 2000, 3000, [4000, 5000, 6000, 7]]
[1001, 2000, 3000, [4000, 5000, 6000, 7]]
[1000, 2000, 3000, [4000, 5000, 6000, 7]]
可见,当lt2为lt的浅拷贝对象时,lt内的可变类型变化,lt2变化;lt内的不可变类型变化,lt2不变化
深拷贝
深拷贝一般用法为:copy.deepcopy()
深拷贝和前拷贝又有什么区别呢?我们还是用代码一探究竟吧
import copy
lt = [1000, 2000, 3000, [4000, 5000, 6000]]
print('id(lt)',id(lt))
print('id(lt[0])', id(lt[0]))
print('id(lt[1])', id(lt[1]))
print('id(lt[2])', id(lt[2]))
print('id(lt[3])', id(lt[3]))
print('*' * 50)
lt2 = copy.deepcopy(lt)
print('id(lt2)',id(lt2))
print('id(lt2[0])', id(lt2[0]))
print('id(lt2[1])', id(lt2[1]))
print('id(lt2[2])', id(lt2[2]))
print('id(lt2[3])', id(lt2[3]))
结果为:
id(lt) 2125003250120
id(lt[0]) 2125000777488
id(lt[1]) 2125001026224
id(lt[2]) 2125001026192
id(lt[3]) 2125003249928
id(lt2) 2125003251400
id(lt2[0]) 2125000777488
id(lt2[1]) 2125001026224
id(lt2[2]) 2125001026192
id(lt2[3]) 2125003251336
[1000, 2000, 3000, [4000, 5000, 6000, 7]]
[1000, 2000, 3000, [4000, 5000, 6000]]
牢记拷贝/浅拷贝/深拷贝只针对可变数据类型
但是虽然看似很重要,但是实际上的应用却不是很多。。
异常处理
异常:报错
语法异常
错误都是 SytaxError
if # SyntaxError
0 = 1 # SyntaxError
逻辑异常
错误的类型往往不一样
1/0 # ZeroDivisionError
dic = {}
print(dic['skldfj']) # KeyError
try方法
try方法无法捕捉语法错误
try:
if
except Exception as e: # 语法错误无法捕捉
print(e)
会报错
但是逻辑错误可以捕捉:
print(1)
try: # 尝试
num = input('输入一个值') # 123124
dic = {'0': 'a'}
print(dic[num]) # dic['123124']
print(3) # 代码自上而下,上面会运行
1 / int(num) # 错误不影响其他的代码,报错马上终止try缩进里面的代码
print(4)
except ZeroDivisionError as e: # 除此之外 # try里面的代码出了什么错误,就得用什么错误捕捉 # as是把错误赋值给e
print('e:', e)
except KeyError as e: # 可以写多个except捕捉多个异常
print('e:', e)
结果为:
1
输入一个值123
e: '123'
except可以捕捉异常
print(1)
try: # 尝试
1 / 1
except Exception as e: # Exception可以捕捉任意异常
print('e:', e)
finally: # 最终的意思,无论报不报错都会打印 明天讲文件处理的时候带着你用
print(3)
print(2)
结果为:
1
3
2
finally无论报不报错都会打印
raise
主动抛错,一般用于创建框架/创建语言 c/c++有用
print(1)
raise ZeroDivisionError('傻逼吧,主动抛错干嘛')
print(2)
结果为:
1
Traceback (most recent call last):
File "xxxx/xxx.py", line xx, in <module>
raise ZeroDivisionError('傻逼吧,主动抛错干嘛')
ZeroDivisionError: 傻逼吧,主动抛错干嘛