对象引用

1. 变量

变量a和b引用同一个列表对象

>>> a = [1, 2, 3]
>>> b = a
>>> id(a), id(b)
(2085930269824, 2085930269824
>>> b.append(4)
>>> a
[1, 2, 3, 4]

变量a和b在这里共同标注着一个对象,变量b也是这一对象的另一个别名

2. == 和 is

变量a和变量c分别绑定同一个列表

>>> a = [1, 2, 3, 4]
>>> c = [1, 2, 3, 4]
>>> a is c
False
>>> a == c
True
>>> id(a), id(c)
(2085930269696, 2085930285184)

变量a和变量使用“==”比较的结果相等,返回True,使用is运算符检查是则返回False

==运算符比较两个对象的值,is运算符比较对象的标识,也就是id()返回对象的内存地址

  • == 和 is的选择

通常的,我们关心的是值,则使用==,如果在变量与单例值之间比较时,应该使用is。

比如,最常使用is检查变量绑定的值是不是None,在阅读别人编写的代码中经常看到它们身影,作为参数的默认值。

类似这样的写法:x is None | x is not None

is运算符比==速度快,因为它不用重载,所以Python不用寻找并调用特殊方法,而是直接比较两个整数ID。而a == b是语法糖,等同于a._eq_(b),继承object的__eq__方法比较两个对象的ID。

3. 元组的相对不可变性

元组和多数Python集合(列表、字典、集)一样,保存的是对象的引用。如果引用的元素是可变的,即便元组本身不可变,元素依然可变。也就是说,元组的不可变性其实是指tuple数据结构的物理内容(即保存的引用)不可变,与引用的对象无关。

元组的值会随着引用的可变对象的变化而变,元组中不可变的是元素的标识。

如下示例,修改t1中的一个可变元素,最后t1的值变了,但是标识没变。

>>> t1 = (1, 2, [30, 40])
>>> id(t1)
2085930158144
>>> t1[-1].append(50)
>>> t1
(1, 2, [30, 40, 50])
>>> id(t1)
2085930158144

4. 浅复制和深复制

浅复制:引用对象一部分内容做了拷贝(副本)

深复制:引用对象所有内容做了拷贝(副本)

下面展示的浅复制示例:

>>> import copy
>>> y = [1, 2, [30, 40, 50]]		# y是一个2层的容器
>>> y1 = copy.copy(y)			# 创建y1副本(浅复制)
>>> id(y),id(y1)			# 查看y,y1的标识
(2085930286592, 2085930286464)
>>> y1[0] = '1'				# 修改副本y1的第一个元素
>>> y1
['1', 2, [30, 40, 50]]
>>> y					# 查看原列表y的结果,没有受到影响
[1, 2, [30, 40, 50]]
>>> y1[-1] += [60]		        # 修改副本y1最后一个元素(第二层)
>>> y1					# 查看副本y1的结果
['1', 2, [30, 40, 50, 60]]
>>> y					# 查看原列表y的结果,第二层被修改后,结果受到影响
[1, 2, [30, 40, 50, 60]]

#####################################
# 使用内置的类型构造方法 -->list或[:]
####################################
>>> y2 = list(y)  			# 复制列表,y2是y的副本(浅复制)
>>> y2						
[1, 2, [30, 40, 50, 60]]
>>> id(y), id(y2)			# 查看y,y2的标识
(2085930286592, 2085936796032)
>>> y == y2				# 比较y,y2的值
True
# -----------------------------
>>> y3 = y[:]				# 复制列表,y3是y的副本(浅复制)
>>> y3
[1, 2, [30, 40, 50, 60]]
>>> id(y), id(y3)			# 查看y,y3的标识
(2085930286592, 2085930286656)
>>> y == y3				# 比较y,y2的值
True

上面的示例中,通过copy方法、构造方法或[:]做到了浅复制。

浅复制,即复制了最外层容器,副本中的元素仍是原容器中的元素引用。

建议使用Python Tutor网站查看交互动画来加深理解,如下就是上面运行的结果其中的一张动画图。

image

下面展示是深复制示例:

>>> y4 = copy.deepcopy(y)
>>> y4
[1, 2, [30, 40, 50, 60]]
>>> id(y),id(y4)
(2085930286592, 2085936774592)
>>> y4[-1] += [70]
>>> y4
[1, 2, [30, 40, 50, 60, 70]]
>>> y
[1, 2, [30, 40, 50, 60]]

如果你看完了浅复制后再来看深复制,很容易的记住它们。

5. 总结

本篇内容仅仅是个人的理解,最后梳洗成文,文中摘抄了很多流畅的python上的专业名词。

这也算某一小小的板块的一点总结,后续有更多心得,再倾注文中。

我知道这还没完,随着对Python越深入学习,越发觉自己菜。

文中如有错误,欢迎大家指出,如君共勉~

posted @ 2021-08-01 18:55  Rosaany  阅读(41)  评论(0编辑  收藏  举报