更多教程请私信~

来源:思路实验室 

作者:室长

大家好,欢迎收看思路实验室出品的Python入门教程,我是室长。

大家好,欢迎收看思路实验室出品的Python入门教程,我是室长。

在之前的学习中,我们得到了几条基础知识:

1.在Python中,万物皆对象。

2.对象分为可变对象和不可变对象。

3.变量里存储的不是值,而是对象所在的内存地址。

那么当可变对象发生变化的时候,并不代表着它的内存地址也发生变化。所以就会出现这样的情况:

python clone() python clone()方法隐藏克隆体_内存地址

周树人起了个笔名叫鲁迅,但是不管是周树人还是鲁迅都是同一个人。“抓捕周树人跟我鲁迅有什么关系”纯粹是因为抓人的吃了没文化的亏。

我让变量a和变量b同时指向一个可变对象(比如列表、字典和集合),然后改变这个对象,那通过访问变量a和变量b得到的结果都会发生改变。

python clone() python clone()方法隐藏克隆体_python_02

python clone() python clone()方法隐藏克隆体_开发语言_03

但是在实际使用中,我们往往不希望进行这样的操作,而是希望a和b是不同的列表,只不过是值一样,对其中一个的改变不影响另一个。这时候用等号去赋值就不管用了。

好在,常见的可变对象都有一个copy方法,用来对这个对象进行克隆,生成一个一模一样的对象(给鲁迅克隆一个周树人来顶包,好像顺序不对)

python clone() python clone()方法隐藏克隆体_Python_04

python clone() python clone()方法隐藏克隆体_开发语言_05

这里b虽然和a一开始的值一样,但已经不是同一个列表了。当使用了copy方法之后,a走a的阳关道,b过b的独木桥,从此山高路远,纵马扬鞭……

然而真的就从此不再有关系了吗?我们来看这样一个例子:

python clone() python clone()方法隐藏克隆体_内存地址_06

这里的a是一个嵌套列表的列表:

python clone() python clone()方法隐藏克隆体_python clone()_07

我们使用copy方法克隆一下这个列表:

python clone() python clone()方法隐藏克隆体_Python_08

python clone() python clone()方法隐藏克隆体_内存地址_09

没有问题。我们改动一下a列表:

python clone() python clone()方法隐藏克隆体_python clone()_10

python clone() python clone()方法隐藏克隆体_Python_11

b并没有受到影响,那如果我们改动一下c呢?

python clone() python clone()方法隐藏克隆体_内存地址_12

python clone() python clone()方法隐藏克隆体_开发语言_13

明明是克隆了一个新列表,怎么b还跟c有关系?

我们以为,一旦用copy方法克隆了a,克隆后的列表就是[1,[1,2]]了,但事实上并非如此,克隆后的列表仍是[1,c]。

所以我们不难看出,列表里存储的也并非是具体的对象,而是对象所在的内存地址。同理,作为可变对象的字典和集合也是如此。

我们使用copy方法克隆的是当前对象存储的内容,也就是一系列的内存地址,而不是具体的值。因此这个copy方法被称为浅拷贝

而有时候我们就希望能够把当前对象里的所有值克隆下来,成为一个完全独立的新对象,任何别的地方的改动都影响不到它。这当然可以,而这种方法被称为深拷贝。不过深拷贝就不是对象自带的方法了,我们需要使用copy模块里的deepcopy函数

python clone() python clone()方法隐藏克隆体_Python_14

python clone() python clone()方法隐藏克隆体_python clone()_15

这一期我们了解了浅拷贝和深拷贝的操作方法。在实际操作中,常常存在对可变对象直接使用等号赋值而没有用拷贝方法或者用错拷贝方法导致的错误。变量值、列表(集合)元素、字典键值,本质上都是对象的内存地址。牢记这一点,你就可以正确地运用等号赋值和拷贝方法。

在编写程序的时候,我们都是要做到没有bug不报错的。但是有些时候运行程序时需要外界的输入,而这些输入不一定就符合程序的要求。如果就因为输入的错误导致了程序整个报错关闭,那有问题的不是输入而是程序本身。那要如何避免这种问题呢?请关注下期:这根本就不是我的错嘛!Python的异常处理。