Python之“is和==的区别“与“浅拷贝和深拷贝”

Python之“is和==的区别“与“浅拷贝和深拷贝”

  • is和==的区别

id():在内存中存储的位置
type:变量的类型
value:变量的值
==:type value
is:type value id

>>> a = '1'
>>> b = 1
>>> a == b
False
>>> a is b
False
>>> a = '1'
>>> b = a
>>> a == b
True
>>> a is b
True

列表:请在python3版本交互式测试

>>> li = [1,2,3]
>>> li1 = li
>>> li1
[1, 2, 3]
>>> id(li)
140586383299272
>>> id(li1)
140586383299272
>>> li2 = li.copy()
>>> li2
[1, 2, 3]
>>> id(li2)
140586383300872
>>> li == li1
True
>>> li1 == li2
True
>>> li2 is li
False
>>> li2 is li1
False
>>> li1 is li
True

结论:.copy拷贝的与直接“=”赋值的在内存中存储的位置不同,因为在用“is”判断时虽然值相等,但是还是会false,也就是说“is”相较于“==”,除了会判断变量的类型和变量的值,还会判断id,即变量在内存中的存储位置

  • 浅拷贝与深拷贝

当一个变量==xx的时候,约定为:指向地址的过程
import copy :调用拷贝模块
浅拷贝:copy.copy()
深拷贝:copy.deepcopy()

列表中比较浅拷贝与深拷贝的不同:

>>> a = [11,22]
>>> b = [33,44]
>>> c = [a,b]
>>> c
[[11, 22], [33, 44]]
>>> import copy
>>> d = copy.copy(c)
>>> d
[[11, 22], [33, 44]]
>>> id(c)
140484660926944
>>> id(d)
140484660995352
>>> id(c[0])
140484660765976
>>> id(d[0])
140484660765976
>>> id(a)
140484660765976
>>> e =  copy.deepcopy(c)
>>> e
[[11, 22], [33, 44]]
>>> id(e)
140484660927232
>>> id(c)
140484660926944
>>> id(e[1])
140484660970776
>>> id(c[1])
140484660853360
>>> id(d[1])
140484660853360
>>> id(b)
140484660853360
>>> a.append(77)
>>> c
[[11, 22, 77], [33, 44], [55, 66]]
>>> d
[[11, 22, 77], [33, 44]]
>>> e
[[11, 22], [33, 44]]
>>> c.append([55,66])
>>> c
[[11, 22], [33, 44], [55, 66]]
>>> d
[[11, 22], [33, 44]]
>>> e
[[11, 22], [33, 44]]

现象及结论:虽然浅拷贝与深拷贝的列表的id都发生了变化,但是通过比较列表中元素的id发现,浅拷贝与原列表中的元素的id没有发生变化,而深拷贝与原列表中的元素id发生了变化,所以结论就是,深拷贝会改变数列包括其中元素所有的id(内存中存储位置)如果给列表添加元素时,浅拷贝由于与原列表中元素存储位置的相同,所以给原列表中元素中添加元素时,浅拷贝会同步,而给原列表添加新元素时,浅拷贝与深拷贝都不会同步

元组中比较浅拷贝与深拷贝的不同:

>>> a = [11,22]
>>> b = [33,44]
>>> c = (a,b)
>>> c
([11, 22], [33, 44])
>>> import copy
>>> d = copy.copy(c)
>>> id(c)
140484660821024
>>> id(d)
140484660821024
>>> e = copy.deepcopy(c)
>>> id(c)
140484660821024
>>> id (e)
140484660820880
>>> id(c[1])
140484660969840
>>> id(d[1])
140484660969840
>>> id(e[1])
140484660853360
>>> a.append(66)
>>> c
([11, 22, 66], [33, 44])
>>> d
([11, 22, 66], [33, 44])
>>> e
([11, 22], [33, 44])
>>> a = (11,22)
>>> b = (33,44)
>>> c = (a,b)
>>> c
((11, 22), (33, 44))
>>> import copy
>>> d = copy.copy(c)
>>> d
((11, 22), (33, 44))
>>> e = copy.deepcopy(c)
>>> e
((11, 22), (33, 44))
>>> id(c)
139840065999648
>>> id(d)
139840065999648
>>> id(e)
139840065999648
>>> id(a)
139840065998648
>>> id(c[0])
139840065998648
>>> id(d[0])
139840065998648
>>> id(e[0])
139840065998648

现象及结论:
如果(copy.copy)拷贝的是元组,那么它不会进行浅拷贝,仅仅是指向,因为元组是不可变数据类型,那么意味着数据一定不能修改,因此copy.copy()的时候它会自动判断是指向
如果用copy.copy() copy.deepcopy()对一个全部是不可变类型的数据进行数据拷贝的时候,那么它们的结果相同,都是引用
如果拷贝的是一个拥有可变类型的数据,那么deepcopy依然是深拷贝,copy是浅拷贝

  • 赋值、深拷贝和浅拷贝的区别

直接赋值(li1 = li):只传递对象的引用, li1指向对象li的内存地址空间。因此, 原有列表li改变, 被赋值的li1也会做相应的改变。

拷贝(li1 = li.copy):与直接赋值相比,li1会重新指向新的内存地址空间。因此,原由列表li改变,拷贝的li1不会改变。与浅拷贝(copy.copy)相同

浅拷贝:li和li2的内存地址不同,但是子对象的内存地址相同,因此,原始数据改变 , 子对象也改变。

扫描二维码关注公众号,回复: 6426005 查看本文章

深拷贝(import copy, eg: li3=copy.deepcopy(li)):li和li3的内存地址不同,包含子对象的拷贝, 所以原始对象改变并不会造成深拷贝里面任何子项的改变。

当深拷贝和浅拷贝, 针对的对象全部是不可变数据类型时, 两者效果相同;
当深拷贝和浅拷贝, 针对的对象包含是可变数据类型时, 两者才有上述区别。

所有的数值类型和bool类型, str是不可变数据类型,
list是可变数据类型;

  • 回顾综合练习

模拟轮盘抽奖游戏
轮盘分为三部分: 一等奖, 二等奖和三等奖;
轮盘转的时候是随机的,
如果范围在[0,0.08)之间,代表一等奖,
如果范围在[0.08,0.3)之间,代表2等奖,
如果范围在[0.3, 1.0)之间,代表3等奖,
模拟本次活动1000人参加, 模拟游戏时需要准备各等级奖品的个数.

import random
#print(random.random())
rewardDict = {
    '一等奖':(0,0.08),
    '二等奖':(0.08,0.3),
    '三等奖':(0.3,1)
}

def rewardFun():
    """用户的得奖等级"""
    # 生成一个0~1之间的随机数
    number = random.random()
    # 判断随机转盘是几等奖
    for k,v in rewardDict.items():
        if v[0] <=number <v[1]:
            return k
#print(rewardFun())

resultDict={}
for i in range(1000):
    res = rewardFun()
    if res not in resultDict:
        resultDict[res] = 1
    else:
        resultDict[res] += 1

for k,v in resultDict.items():
    print(k,'---->',v)

END

猜你喜欢

转载自blog.csdn.net/weixin_44828950/article/details/90693149