# 15-Python 对象的比较、拷贝

AI悦创原创Python 进阶Python 进阶大约 11 分钟...约 3413 字

``````if a == b:
...
``````

``````l1 = [1, 2, 3]
l2 = list(l1)
``````

• l2 是 l1 的浅拷贝（shallow copy）还是深度拷贝（deep copy）呢？
• `a == b` 是比较两个对象的值相等，还是两个对象完全相等呢？

## 1. '==' VS 'is'

``````a == b
``````

`'is'` 操作符比较的是对象的身份标识是否相等，即它们是否是同一个对象，是否指向同一个内存地址。

``````a = 10
b = 10

a == b
True

id(a)
4427562448

id(b)
4427562448

a is b
True
``````

``````a = 257
b = 257

a == b
True

id(a)
4473417552

id(b)
4473417584

a is b
False
``````

``````if a is None:
...

if a is not None:
...
``````

``````t1 = (1, 2, [3, 4])
t2 = (1, 2, [3, 4])
t1 == t2
True

t1[-1].append(5)
t1 == t2
False
``````

## 2. 浅拷贝和深度拷贝

``````l1 = [1, 2, 3]
l2 = list(l1)

l2
[1, 2, 3]

l1 == l2
True

l1 is l2
False

s1 = set([1, 2, 3])
s2 = set(s1)

s2
{1, 2, 3}

s1 == s2
True

s1 is s2
False
``````

``````l1 = [1, 2, 3]
l2 = l1[:]

l1 == l2
True

l1 is l2
False
``````

``````import copy
l1 = [1, 2, 3]
l2 = copy.copy(l1)
``````

``````t1 = (1, 2, 3)
t2 = tuple(t1)

t1 == t2
True

t1 is t2
True
``````

``````l1 = [[1, 2], (30, 40)]
l2 = list(l1)
l1.append(100)
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2
[[1, 2, 3], (30, 40)]

l1[1] += (50, 60)
l1
[[1, 2, 3], (30, 40, 50, 60), 100]

l2
[[1, 2, 3], (30, 40)]
``````

``````[[1, 2, 3], (30, 40), 100]
``````

``````l1: [[1, 2, 3], (30, 40), 100]
l2: [[1, 2, 3], (30, 40)]
``````

``````l1: [[1, 2, 3], (30, 40, 50, 60), 100]
``````

Python 中以 `copy.deepcopy()` 来实现对象的深度拷贝。比如上述例子写成下面的形式，就是深度拷贝：

``````import copy
l1 = [[1, 2], (30, 40)]
l2 = copy.deepcopy(l1)
l1.append(100)
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2
[[1, 2], (30, 40)]
``````

``````import copy
x = [1]
x.append(x)

x
[1, [...]]

y = copy.deepcopy(x)
y
[1, [...]]
``````

``````def deepcopy(x, memo=None, _nil=[]):
"""Deep copy operation on arbitrary Python objects.

"""

if memo is None:
memo = {}
d = id(x) # 查询被拷贝对象x的id
y = memo.get(d, _nil) # 查询字典里是否已经存储了该对象
if y is not _nil:
return y # 如果字典里已经存储了将要拷贝的对象，则直接返回
...
``````

## 3. 总结

• 比较操作符 `'=='` 表示比较对象间的值是否相等，而 `'is'` 表示比较对象的标识是否相等，即它们是否指向同一个内存地址。
• 比较操作符 `'is'` 效率优于`'=='`，因为 `'is'` 操作符无法被重载，执行 `'is'` 操作只是简单的获取对象的 ID，并进行比较；而 `'=='` 操作符则会递归地遍历对象的所有值，并逐一比较。
• 浅拷贝中的元素，是原对象中子对象的引用，因此，如果原对象中的元素是可变的，改变其也会影响拷贝后的对象，存在一定的副作用。
• 深度拷贝则会递归地拷贝原对象中的每一个子对象，因此拷贝后的对象和原对象互不相关。另外，深度拷贝中会维护一个字典，记录已经拷贝的对象及其 ID，来提高效率并防止无限递归的发生。

## 4. 思考题

``````import copy
x = [1]
x.append(x)

y = copy.deepcopy(x)

# 以下命令的输出是？
x == y
``````

AI悦创·编程一对一

AI悦创·推出辅导班啦，包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」，全部都是一对一教学：一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然，还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线，随时响应！微信：Jiabcdefh

C++ 信息奥赛题解，长期更新！长期招收一对一中小学信息奥赛集训，莆田、厦门地区有机会线下上门，其他地区线上。微信：Jiabcdefh

• 0
• 0
• 0
• 0
• 0
• 0

• 按正序
• 按倒序
• 按热度