字典
概念
无序的,可变的键值对的集合
定义
- 方式一直接定义:
person = {"name": "sz", "age": 18}
print(person, type(person))
print(person["name"])
print(person["age"])
输出:
- 利用fromkeys类调用
d = dict.fromkeys("abc",666) # 将该序列的每个元素赋值列表
print(d)
输出:
{‘a’: 666, ‘b’: 666, ‘c’: 666}
注意:key不能重复(重复的话后值会把前值覆盖掉),并且为不可变类型(所谓不可变类型指的是在同一内存下,其不可再次改变)
如:
num =[1,2,3]
print(num, id(num))
num.append(4)
print(num, id(num))
num=1
print(num, id(num))
num=2
print(num, id(num))
虽然num和列表都变动了,但num赋值的存储地址变了,而列表其存储地址都是271…224,证明列表为可变;赋值这个是不可变的。
原因:
Python的字典,采用的是哈希(hash)的方式来实现的。
其存储过程为:
- 初始化一个表格,用来存放所有的值。这个表格称之为"哈希表,暂且可理解为我们所学的“列表”。
- 在存储一个键值对的时候,会作以下操作:根据给定的key,通过某些操作,得到一个在"哈希表"中的索引位置;把key通过"哈希函数"转换成一个整型数字(称为“哈希值”),将该数字对数组长度进行取余,取余结果就当作数组的下标;如果产生了"哈希冲突",比如,两个不同的key,计算出来的索引是同一个则采用”开发寻址法",通过探测函数查找下一个空位。
再根据索引位置,存储给定的"值”。
其单查找过程为:
再次使用哈希函数将key转换为对应的列表的索引,并定位到列表的位置获取value。
意义
可以通过key,访问对应的值,使得这种访问更具意义。
查询效率得到很大提升,可类比为"汉字字典”的使用方式。
操作
增
# dic[key]=value
d={"name": "ss", "age": 48}
print(d, type(d), id(d))
d["height"]=180 # 新增操作
print(d, id(d)) # 地址位置相同(改的还是之前的对象)
输出:
删
# 1. del dic[key] 删除
d={'name': 'ss', 'age': 48, 'height': 180}
del d['name'] # 若没有对应的关键词则报错
print(d)
# 2. dic.pop(key[,default]) 删除指定键值对,并返回对应值
d={'name': 'ss', 'age': 48, 'height': 180}
v=d.pop("age")
print(v,d)
v1=d.pop('age1', 66) # 若key不存在,则返回给定的default值,若没设置该值会报错
print(v1, d)
# 3. dic.popitem() 删除按升序排序后的第一个键值对,并以元组的形式返回该键值对
d={'name': 'ss', 'sge': 48, 'a': 18}
re=d.popitem()
print(re,d) # 发现把a给干掉了
# 4. dic.clear() 删除字典内的所有键值对,但保留该字典只是为空了,不同于del是删除了
d={'name': 'ss', 'sge': 48, 'a': 18}
print(d.clear())
print(d)
输出:
改
改的是值,不是字典关键字
# 1. dic[key]=value
d={"name": "ss", "age": 48}
d["age"]=180 # 修改操作
d["tall"]=180 # 若不存在是新增
print(d)
# 2. oldDic.update(newDic) 批量修改键值对
d={"name": "ss", "age": 48}
d.update({'age': 666, 'address':'上海'}) # 改一个增一个
print(d)
输出:
查
- 获取单个值
# 1. dic[key]
d={"name": "ss", "age": 48}
print(d['age'])
# 2. dic.get(key[,default])
d={'name': 'ss', 'age': 666, 'address': '上海'}
v=d.get('name')
v1=d.get(0,666) # 若key不存在则返回设定值
print(v,v1,d)
# 3. dic.setdefault(key[,default])
d={'name': 'ss', 'age': 666, 'address': '上海'}
v=d.setdefault('age1',555) # 跟get差不多,但区别于若key不存在,此操作会对原字典进行添加
print(v,d)
输出:
- 获取多个
# 1. 获取所有的值
d={'name': 'ss', 'age': 666, 'address': '上海'}
print(d.values())
# 2. 获取所有的键
print(d.keys())
# 3. 获取所有键值对
print(d.items())
# 注意:他还是不支持索引,他的类型为view objects
输出:
遍历
# 1. 先遍历所有keys,然后根据key获取对应的值
d={'name': 'ss', 'age': 666, 'address': '上海'}
keys=d.keys()
for key in keys:
print(key, d[key])
# 2. 直接遍历所有的键值对
kvs=d.items() # 获取所有键值对
for t in kvs:
print(t)
k, v = t # 解包
print(k,v)
输出:
计算和判定
d={'name': 'ss', 'age': 666, 'address': '上海'}
print(len(d)) # 计算键值对个数
print('name' in d) # 判定的是key
输出:
集合
概念
无序的,不可随机访问的,不可重复的元素集合
与数学中集合的概念类似,可对其进行交、并、差、补等逻运算
分为可变集合和非可变集合:set 为可变集合(增删改);frozenset 为不可变集合(创建好之后无法增删改)
定义
可变集合
s = {1,2,3,4}
s = set(iterable) # 转化为集合
s = set(x for x in range(1,10)) # 集合推导式
iterable可以是字符串、列表、元组、字典等
不可变集合
fs = frozenset(iterable)
s = frozenset(x for x in range(1,10)) # 集合推导式
注意事项:
- 创建一个空集合时,需要使用set()或者 frozenset(),不能使用s={},因为会被识别成为字典
- 集合中的元素,必须是可哈希的值。指的是如果一个对象在自己的生命周期中有一哈希值(hash value)是不可改变的那么它就是可哈希(hashable)的(可理解为不可变类型)
- 如果集合中的元素值出现重复,则会被合并为1个
操作
单一集合操作
增
# 增
s={1,2,3}
s.add(4)
print(s)
输出:
{1, 2, 3, 4}
删
# 删
s={1,2,3}
res=s.remove(3) # 会改变集合本身
print(res,s)
s={1,2,3}
res2=s.discard(13) # 若集合不存在13,则也不会报错的删除操作
print(res2,s)
s={1,2,3}
res3=s.pop() # 删除第一个元素
print(res3,s)
s={1,2,3}
res4=s.clear() # 清空集合元素
print(res4,s)
输出:
查
因为无法通过索引或key进行查询
所以我们只能进行遍历
- for in 遍历
s={1,2,3}
for i in s:
print(i)
输出:
1
2
3
- 迭代器遍历
s={1,2,3}
# 1.生成迭代器
its=iter(s)
# 2.使用这个迭代器访问
for i in its:
print(i)
输出:
1
2
3
对于不可变集合的查询,也是一样的
集合之间操作
交集
# 集合本身不发生改变
# 1.intersection()
s1={1,2,3,4,5}
s2={4,5,6}
result=s1.intersection(s2) # 求两个集合的交集
print(result,type(result))
# 若其中一个为不可变集合(结果取决于最先取交集的是可变还是不可变为准)
s3=frozenset([1,2,3])
result2=s1.intersection(s3) # 结果为可变集合
print(result2,type(result2))
result3=s3.intersection(s1)
print(result3,type(result3)) # 结果为不可变集合
# 2.&
s1={1,2,3,4,5}
s2={4,5,6}
result=s1&s2 # 求两个集合的交集
print(result,type(result))
# 集合本身发生改变
s1={1,2,3,4,5}
s2={4,5,6}
result=s1.intersection_update(s2)
print(result,type(result)) # 因为改变的是集合本身所以返回空值
print(s1,s2) #
输出:
注意:若字符串的数字则必须是字符串才交集有效,对应的内容+对应的类型相同才算完全相交
s1={1,2,3,4,5}
s2={'1','2','3','4','5'}
print(s1.intersection("123"))
print(s1.intersection(["1","2",'6']))
print(s2.intersection("123"))
print(s2.intersection(["1","2",'6']))
输出:
并集
# 可变集合
s1={1,2,3}
s2={3,4,5,6}
res=s1.union(s2) # 不改变原集合进行并集
print(res,s1)
res=s1|s2 # 可以使用|
print(res,s1)
res3=s1.update(s2)
print(res3,s1)
# 不可变集合
s3=frozenset([1,2,3])
res3=s3|s2
print(res3,s3)
输出:
差值
# 不修改原对象
s1={1,2,3}
s2={3,4,5,6}
res1=s1.difference(s2)
print(res1,s1)
res2=s1-s2
print(res2,s1)
# 修改原对象
res3=s1.difference_update(s2)
print(res3,s1)
输出:
判定
s1={1,2,3}
s2={3,4,5,6}
s3={1,2}
# 判定isdisjoint()两个集合不相交
print(s1.isdisjoint(s2))
print(s3.isdisjoint(s2))
# issuperset()一个集合完全包含另一个集合
print(s1.issuperset(s2))
print(s1.issuperset(s3))
# issubset()一个集合包含于另一个集合(子集合)
print(s3.issubset(s1))
输出: