Python对象的比较和拷贝

李文轩 2019-08-17
声明:这是本人学习极客时间的Python核心技术与实战的笔记,有侵权请联系我。


  1. ' == ' VS ' is '
  2. 浅拷贝(shallow copy)与深拷贝(deep copy)

' == ' VS ' is '

==is 都是Python中对象比较常用的两种方式。== 操作符会比较两个变量的值是否相等;而 is 操作符则会比较两个对象的 ID 是否相等。(Python 中,可以通过 id(object) 的函数获得每个对象的身份标识。)

例子:

# 整数作为例子的对象比较
    
a = 10
b = 10
    
a == b
# 输出 # True
    
id(a)
4427562448
    
id(b)
4427562448
    
a is b
# 输出 # True

在整数变量的比较中,如果两个值相同的变量在[-5, 256] 的范围外的话,==会依旧返回True,因为值是相同的。is 不会返回True,因为在[-5, 256]范围外的整数,不管如何,Python都会分别为值一样的整数开辟一段新的内存。范围内的整数则是用数组维持,作为缓存使用;所以在范围内的整数都不会重新开辟一块新的内存空间。

例子:

# [-5, 256] 范围外的整数比较

a = 257
b = 257

a == b
# 输出 # True

id(a)
4473417552

id(b)
4473417584

a is b
# 输出 # False

is 不可以被重载,而== 可以。重载==的方法是重载对象的__eq__ 函数。例如,对于列表,__eq__ 函数会去遍历列表中的元素,比较它们的顺序和值是否相等。

对于不可变(immutable)的变量,== 或者 is 的结果不是一直不变的。下面的例子中,元组是不可变,但元组中的列表却是可变的。如果改变了元组中的列表,元组自身也会发生改变;即前后的比较结果不一定相同。

例子:

# 包含可变变量的不可变变量比较

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

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

浅拷贝与深拷贝

浅拷贝是指,重新分配一块内存,创建一个新的对象,里面的元素是原对象中子对象的引用。

列表和集合例子:

# 浅拷贝的操作(列表)

l1 = [1, 2, 3]
l2 = list(l1)
# 如果是序列,切片也能达成:l2 = l1[:]
# copy.copy()函数也可以:l2 = copy.copy(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
# 两个不同的对象,在两个不同的地址

元组例子:

# 浅拷贝的操作(元组)

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 与 l2 是两个不同的对象,
# 可是第一个元素(列表)是指向同一个地址的同一个对象,
# 所以在改变 l1[0] 时,也会改变 l2[0]

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

l2
# 输出 # [[1, 2,3], (30, 40)]
# 元组是不可变的对象,所以为 l1[1] 增加整数时
# 实际上是生成了一个新的元组来替换 l1[1]
# l2[1] 不会改变,l1[1] 和 l2[1] 指向了不同的对象。

深拷贝是指,重新分配一块内存,创建一个新的对象,并且将原来对象中的元素以递归的方式,通过创建新的子对象拷贝到新对象中。自此,新对象和原对象没有任何关联。

#深拷贝的例子

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, [...]]

# 列表 x 中有指向自身的引用
# x 是一个无限嵌套的列表
# 但是深度拷贝后,并没有发生 stack overflow 的现象
# 原因是 deepcopy 函数中会维护一个字典,记录已拷贝的对象与其ID
# 在拷贝过程中,如果字典力已存在将要拷贝的对象,则会从字典直接返回。
# 这个方法有效提高拷贝效率以及防止无限递归的发生。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343