python数据类型之可hash,不可hash
什么是hash呢?
Hash一般译为“散列”,也音译为“哈希”,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,输出的就是散列值。
这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值
来唯一确定输入值。简单说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
可使用的对象包括: 数字 、字符串、元组,不可使用hash函数的是 列表、字典。
hash的特征:hash值的计算过程是以依据这个值的特征计算的,这要求被hash的值必须固定,因此被hash的值必须不可变
可变类型的数据不可哈希,如list,字典,集合:同值不同址,不同值同址
a = [1,2,3]
b = [1,2,3]
print(id(a),id(b)) #2110426618696 2110426618824
a.append(4)
print(id(a)) #2110426618696
数值、字母、字符串、数字、元组不可变:同值同址,不同值不同址
#改变a的值后 内存地址也改变了(id)
怎么判断可变不可变 ?
总结:改个值 看id是不是一样,id一样的为可变,则不可哈希,改了值,id变化,则为不可变,则可哈希
字典:
又叫键值对数据 dict dict = {键:值}
存储数据 字典的查找快一些
python3.6版本以上 字典默认是有序的,怎么写的就怎么打印出来 但是出去别和别人说的时候 字典是无序的
字典的键:不可变数据类型 键不能 不可哈希的,就是可变的数据 可变的数据不能哈希 不可变的数据能哈希
字典的值:可以随意
dic = {'01':'邓新','2':'情哥哥','14':'小冯','98':'啦'}
print(dic['01']) # 通过键去查找
print(dic['2']) # 通过键去查找
增:
dic[11] = '小米'
print(dic)
dic.setdefault(99,'华为') # 99键 华为 值
#1.先去字典中通过99这个键去查有没有值
#2.如果是值 就不添加
#3.如果是None 就添加 返回的是添加的值
删:
del dic #删除整个字典
del dic[键] #通过键删除
print()
print(dic.pop(99)) # pop 通过指点键删除 pop也有返回值 返回的是被删除的值
dic.clear() #清空
print(dic)
dic.popitem() #随机删除 python3.6 删除最后一个 python3.5 随机删除
print(dic)
改:
dic1 = {'33':'jj','44':'TT'}
dic2 = {'33':'gg','66':'pp'}
dic1.update({'33':'gg','66':'yy'}) #更新 被更新的内容如果在 要更新的内容中那值就会覆盖
#两个字典中,都没有一样的就合并
dic1.update(dic2)
dic2['33'] = '啦' #字典的增 是字典中没有的时候才叫增,如果字典中键存在的时候才叫改
查:
dic1 = {'33':'jj','44':'TT'}
print(dic1['33']) #通过键查找 如果键不存在就报错
print(dic1.get('33')) #通过键查找 键不存在不报错 返回None
print(dic1.setdefault('33')) #不存在返回None
其他操作:
dic1 = {'33':'jj','44':'TT'}
for i in dic1:
print(i)
for i in dic1:
print(dic1.get(i))
for i in dic1.keys:
print(dic1.get(i))
print(dic1.keys()) #高仿列表 dic—_keys(['33','66']) 不能使用下标
print(dic1.values()) #高仿列表 dic—_values(['jj','TT']) 不能使用下标
#取出键值
print(dic1.items()) # 取出键值 每部分用元组包起来
解构:
a,b,c = '4','5','6' ['4','5','6'] ('4','5','6') {'1':8,'2':9,'3':0} True,False,True
print(a,b,c)
for k,v in dic1.items():
print(k,b)
#面试题
a = 10
b = 20
a,b = b,a
print(a,b)
补充:
dic2 = {'33':'gg','66':'pp'}
ret1 = dic2.get('99':'啦啦啦')
ret2 = dic2.pop('99':'没有')
print(ret1,ret2)
#坑:
dic3 = dict.formkeys([1,2,3,4,5],[1,2,3]) #第一个是键 要是可迭代的对象
#第二个是值,值是无所谓 是因为创建的新字典的值用的都是一个 值是一个可变数据类型
print(dic3)
dic3[3] = '啦啦啦'
字典的嵌套:
dic = {'汪峰':{'1':'la','2':'啦'},'陈冠希':{'张柏芝':'喜剧之王','阿娇':'千机变'}}
dic1 = dic['陈冠希']
print(dic1['张柏芝'])
集合:
set 集合 存储数据 天然去重 无序的不能使用照片
se = {1,2,3,4,5,1,1,3,4,2,45,3,2}
print(se)
#面试题
lst = [1,2,3,41,12,1,1,12,2]
print(list(set(lst)))
for i in {1,2,3,4}:
print(i)
增:
s = {"刘嘉玲", '关之琳', "王祖贤"}
s.add("郑裕玲") # 重复的内容不会被添加到set集合中
print(s)
s = {"刘嘉玲", '关之琳', "王祖贤"}
s.update("麻花藤") # 迭代更新
print(s)
s.update(["张曼⽟", "李若彤","李若彤"])
print(s)
删:
s = {"刘嘉玲", '关之琳', "王祖贤","张曼⽟", "李若彤"}
item = s.pop() # 随机弹出⼀个.
print(s)
print(item)
s.remove("关之琳") # 直接删除元素
# s.remove("⻢⻁疼") # 不存在这个元素. 删除会报错
print(s)
s.clear() # 清空set集合.需要注意的是set集合如果是空的. 打印出来是set() 因为要和
dict区分的.
print(s) # set()
查:
# set是⼀个可迭代对象. 所以可以进⾏for循环
for el in s:
print(el)
常用操作:
s1 = {"刘能", "赵四", "⽪⻓⼭"}
s2 = {"刘科⻓", "冯乡⻓", "⽪⻓⼭"}
# 交集
# 两个集合中的共有元素
print(s1 & s2) # {'⽪⻓⼭'}
print(s1.intersection(s2)) # {'⽪⻓⼭'}
# 并集
print(s1 | s2) # {'刘科⻓', '冯乡⻓', '赵四', '⽪⻓⼭', '刘能'}
print(s1.union(s2)) # {'刘科⻓', '冯乡⻓', '赵四', '⽪⻓⼭', '刘能'}
# 差集
print(s1 - s2) # {'赵四', '刘能'} 得到第⼀个中单独存在的
print(s1.difference(s2)) # {'赵四', '刘能'}
# 反交集
print(s1 ^ s2) # 两个集合中单独存在的数据 {'冯乡⻓', '刘能', '刘科⻓', '赵四'}
print(s1.symmetric_difference(s2)) # {'冯乡⻓', '刘能', '刘科⻓', '赵四'}
s1 = {"刘能", "赵四"}
s2 = {"刘能", "赵四", "⽪⻓⼭"}
# ⼦集
print(s1 < s2) # set1是set2的⼦集吗? True
print(s1.issubset(s2))
# 超集
print(s1 > s2) # set1是set2的超集吗? False
print(s1.issuperset(s2))
set集合本⾝是可以发⽣改变的. 是不可hash的. 我们可以使⽤frozenset来保存数据. frozenset是不可变的. 也就是⼀个可哈希的数据类型
`s ``=` `frozenset``([``"赵本⼭"``, ``"刘能"``, ``"⽪⻓⼭"``, ``"⻓跪"``])``dic ``=` `{s:``'123'``} ``# 可以正常使⽤了``print``(dic)`