十分钟明白python-赋值和深拷贝和浅拷贝,可哈希不可哈希,可变对象,不可变对象,id,hash函数

一直难以理解一些概念,可哈希,不可哈希,可变元素,不可变元素,python的id和hash函数是干什么的?面试常问的深拷贝和浅拷贝又是干嘛的?这几个概念有什么联系?今天这篇文章就记录一下我对上面几个概念的理解和测试

1.可哈希,不可哈希,可变数据结构,不可变数据结构

可哈希的官方解释,不可哈希则概念相反

An object is hashable if it has a hash value which never changes during its lifetime (it needs a hash() method), and can be compared to other objects (it needs an eq()or cmp() method). Hashable objects which compare equal must have the same hash value.

如果一个对象是可哈希的,那么在它的生存期内必须不可变(而且该对象需要一个哈希函数),而且可以和其他对象比较(需要比较方法).比较值相同的对象一定有相同的哈希值

  • 可变数据结构-不可哈希类型(对于可变对象而言,比如一个列表,更改列表的值,但是对象的地址本身是不变的,也就是说不同的Key,映射到了相同的Value,这显然是不符合哈希值的特性的,即出现了哈希运算里面的冲突)

字典dict,列表list,集合set

  • 不可变数据结构-可哈希类型(对于不可变类型而言,不同的值意味着不同的内存,相同的值存储在相同的内存,可以将我们的不可变对象理解成哈希表中的Key,将内存理解为经过哈希运算的哈希值Value)

数字类型(int,float,bool)字符串str、元组tuple、自定义类的对象

2.id()和hash()

2.1 id()

id() 函数返回对象的唯一标识符,标识符是一个整数。CPython解释器中 中 id() 函数用于获取对象的内存地址。

  • 例子演示

在这里插入图片描述

我们可以看到当我们打印相同值可哈希对象(一个整型)时,输出的id值是一样

打印相同值的不可哈希对象(一个列表)时,输出的id是不一样

2.hash()

hash() 用于获取取一个可哈希对象(字符串或者数值等)的哈希值。

  • 例子演示
  • hash可哈希对象的情况

在这里插入图片描述

  • hash不可哈希对象的情况

在这里插入图片描述

可以看到当hash可哈希对象时,可以输出对应的哈希值,整型的哈希值等于它本身,元组话就输出一个很大的一个整数,并且一个数据对应一个哈希值

当hash不可哈希对象时,直接抛出一个异常

3.深拷贝和浅拷贝

3.1 python的深拷贝和浅拷贝

3.1.1 浅拷贝和赋值
import copy
a = 1
b = [a,[1,2,3,4],{1,3,4,5},(1,2,3,4,5),{"1":1}]
c = b.copy()
d = b
print(id(b))
print(id(d))
print(id(c))

在这里插入图片描述

可以看到浅拷贝和赋值的区别是:

赋值时会将变量指向同一个地址,没有创建新的对象

浅拷贝指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用,就比如c是对b的浅拷贝,但是其中子对象依旧指向是一样的

3.1.2 浅拷贝和可哈希,不可哈希类型的关系
import copy
a = 1
b = [a,[1,2,3,4],{1,3,4,5},(1,2,3,4,5),{"1":1}]
c = b.copy()
c[1][2]=100
c[2].remove(1)
c[3]=c[3]+(100,100)

接下来我们看下面这张图

在这里插入图片描述

b是一个嵌套了整型,列表,集合,元组,字典的一个列表,c对b进行了浅拷贝

①我们对c[0](整型:可哈希类型)进行改变,发现改变c的值并不会改变b的值

②我们对c[1](列表:不可哈希类型)进行改变,发现改变了c的值此时也会改变b[1]的值

③我们对c[2](集合:不可哈希类型)进行改变,发现改变了c[2]的值此时也会改变b[2]的值

④我们对c[3](元组:可哈希类型)进行改变,发现改变c[3]的值并不会改变b的值

由①②③④我们可以发现规律:进行浅拷贝后,改变其中的可哈希子对象不会改变被浅拷贝对象,而改变其中的不可哈希子对象则会改变被拷贝对象

3.1.3深拷贝
import copy
a = 1
b = [a,[1,2,3,4],{1,3,4,5},(1,2,3,4,5),{"1":1}]

d = copy.deepcopy(b)
d[1][2]=100
d[2].remove(1)
d[3]=d[3]+(100,100)

在这里插入图片描述

从上图我们可以看到,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联,此时你改变其中的子对象无论是可哈希类型,还是不可哈希类型,都不会改变原来的被拷贝对象。

参考:

https://www.runoob.com/python/python-func-hash.html

https://www.runoob.com/python/python-func-id.html

https://pythontutor.com/live.html#mode=edit

https://zhuanlan.zhihu.com/p/54011712

觉得我写的不错,对你有帮助的话请给一个赞吧~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值