Python序列的字典类型介绍

描述

字典

介绍

字典是“键值对”的无序可变序列,字典中的每个元素都是一个“键值对”,包含:“键对象”和“值对象”。

可以通过“键对象”实现快速获取、删除、更新对应的“值对象”

字典特点:

无序, 可变, 大括号 {} + 键值对 k,v

字典是 Python 项目中最常用的序列类型之一, 对应Java 中常用的 Json 数据类型

操作

字典的创建

通过 {} + kv

来创建

通过dict()来创建字典对象(两种方式)

过zip()创建字典对象

通过fromkeys创建值为空的字典

字典(类比Json)

“键”是任意的不可变数据,比如:整数、浮点数、字符串、元组. 但是:列表、字典、集合这些可变对象,不能作为“键”.

并且“键”不可重复。

#“值”可以是任意的数据,并且可重复

1. 通过{} 创建字典

a = {'name': 'TimePause',

'age': 18, 'sex': 'man'}

print(a)

2. 通过dict()来创建字典对象(两种方式)

b =

dict(name='TimePause', age=18, sex='man')

a = dict([("name", "TimePause"),

("age", 18)])

print(b)

print(a)

c = {} # 空的字典对象

d = dict() #

空的字典对象

print(c)

print(d)

3. 通过zip()创建字典对象

k = ["name", "age",

"sex"]

v = ["TimePause", 18, "man"]

d = dict(zip(k, v))

print(d) #

{'name': 'TimePause', 'age': 18, 'sex': 'man'}

4. 通过fromkeys创建值为空的字典

f =

dict.fromkeys(["name", "age", "sex"])

print(f) # {'name': None, 'age': None,

'sex': None}

元素的访问:

字典元素的访问

a = {'name': 'TimePause', 'age': 18, 'sex': 'man'}

1. 通过

[键] 获得“值”。若键不存在,则抛出异常。

b = a["name"]

print(b)

#c = a["birthday"]

KeyError: 'birthday'

#print(c)

2. 通过get()方法获得“值”. 推荐使用.

优点是:指定键不存在,返回None;也可以设定指定键不存在时默认返回的对象. 推荐使用get()获取“值对象”

b =

a.get("name")

c = a.get("birthday")

d = a.get("birthday",

"值不存在")

print(b)

print(c)

print(d)

3. 列出所有的键值对

b =

a.items()

print(b) # dict_items([('name', 'TimePause'), ('age', 18), ('sex',

'man')])

4. 列出所有的键,列出所有的值

k = a.keys()

v = a.values()

print(k, v)

dict_keys(['name', 'age', 'sex']) dict_values(['TimePause', 18, 'man'])

  1. len() 键值对的个数

    b = len(a)

    print(b)

6. 检测一个“键”是否在字典中

print("name"

in a) # True

字典元素添加、修改、删除

  1. 给字典新增“键值对”。如果“键”已经存在,则覆盖旧的键值对;如果“键”不存在,则新增“键值对

a =

{'name': 'TimePause', 'age': 18, 'sex': 'man'}

a['name'] =

"时间静止"

a['phone'] = 18322222222

print(a)

  1. 使用 update()

将新字典中所有键值对全部添加到旧字典对象上。如果 key 有重复,则直接覆盖

a = {'name': 'TimePause', 'age': 18,

'sex': 'man'}

b = {'name': '时间静止', 'age': 18, 'phone':

18322222222}

a.update(b) # 旧字典.update(新字典)

print(a)

  1. 字典中元素的删除,可以使用

del() 方法;或者 clear() 删除所有键值对; pop() 删除指定键值对,并返回对应的“值对象

a = {'name':

'TimePause', 'age': 18, 'sex': 'man'}

del (a["name"])

print(a) # {'age':

18, 'sex': 'man'}

a.pop("age")

print(a) # {'sex': 'man'}

popitem() :以后入先出的方式删除和返回该键值对

#删除并返回一个(键,值)对作为 2 元组。对以 LIFO(后进先出)顺序返回。如果 dict

为空,则引发 KeyError。

a = {'name': 'TimePause', 'age': 18, 'sex':

'man'}

a.popitem()

print("第一次调用popitem",

a)

a.popitem()

print("第二次调用popitem",

a)

a.popitem()

print("第三次调用popitem", a)

#a.popitem() # KeyError:

'popitem(): dictionary is empty'

#print("第四次调用popitem", a)

序列解包

序列解包可以用于元组、列表、字典。序列解包可以让我们方便的对多个变量赋值

#序列解包

#序列解包可以用于元组、列表、字典。序列解包可以让我们方便的对多个变量赋值

x, y, z = (20, 30, 10) #

变量

(a, b, c) = (9, 8, 10) # 元组

[m, n, p] = [10, 20, 30] # 列表

序列解包用于字典时,默认是对“键”进行操作;

a = {'name': 'TimePause', 'age': 18, 'sex':

'man'}

name, age, sex = a

print(name)

如果需要对键值对操作,则需要使用items()

name, age, sex = a.items()

print(name)

如果需要对“键”进行操作,则需要使用keys()

name, age, sex = a.keys()

print(name)

如果需要对“值”进行操作,则需要使用values()

name, age, sex = a.values()

print(name)

18

表格数据使用字典和列表存储访问

#表格数据使用字典和列表存储访问

#定义字典对象

a1 = {"name": "才子队", "season": 1, "winner":

"比尔"}

a2 = {"name": "九头蛇队", "season": 2, "winner": "皮尔斯"}

a3 = {"name":

"巨亨队", "season": 3, "winner": "卡罗尔"}

#定义列表对象tl

tl = [a1, a2,

a3]

print(tl)

print(tl[1].get("name"))

#输出所有获胜人员名称

for x in

range(3):

print(tl[x].get("winner"))

#打印表的所有数据

for i in

range(len(tl)):

print(tl[i].get("name"), tl[i].get("season"),

tl[i].get("winner"))

字典核心底层原理(重要)

: 将一个键值对放进字典的底层过程

字典对象的核心是散列表. 散列表是一个稀疏数组(总是有空白元素的数组)

数组的每个单元叫做 bucket. 每个 bucket

有两部分:一个是键对象的引用,一个是值对象的引用

由于所有 bucket 结构和大小一致,我们可以通过偏移量来读取指定bucket

下面操作将一个键值对放入字典

假设字典a对象创建完后,数组长度为8

a =

{}

a["name"]="比尔"

我们要把”name”=”比尔”这个键值对放到字典对象a中,

首先第一步需要计算键”name”的散列值。Python中可以通过hash()来计算。

下面我们通过

Python Console 来查看 name 的hash值

bin(hash("name"))

'-0b1010111101001110110101100100101'

由于数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即“101”,十进制是数字5。

我们查看偏移量6对应的bucket是否为空

如果为空,则将键值对放进去。如果不为空,则依次取右边3位作为偏移量,即“100”,十进制是数字4

再查看偏移量为7的bucket是否为空。直到找到为空的bucket将键值对放进去.

流程图如下:

python

字典扩容

python会根据散列表的拥挤程度扩容。“扩容”指的是:创造更大的数组,将原有内容拷贝到新数组中。

接近2/3时,数组就会扩容

二. 根据键查找“键值对”的底层过程

通过 Python console() 查看字典元素值如下

a.get("name")

'比尔'

1

2

当调用a.get(“name”),就是根据键“name”查找到“键值对”,从而找到值对象“比尔”。

我们仍然要首先计算“name”对象的散列值:

bin(hash("name"))

'-0b1010111101001110110101100100101'

1

2

和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。

假设数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即

101 ,十进制是数字5。

我们查看偏移量5,对应的 bucket 是否为空。如果为空,则返回 None 。

如果不为空,则将这个 bucket

的键对象计算对应散列值,和我们的散列值进行比较,

如果相等。则将对应“值对象”返回。

如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后,仍然没有找到。则返回None

流程图如下:

python

用法总结:

字典在内存中开销巨大 (空间换时间)

键查询速度很快

(通过位运算+Hash运算)

往字典里面添加新键值对可能导致扩容,导致散列表中键的次序变化。

因此,不要在遍历字典的同时进行字典的修改

键必须可散列

数字、字符串、元组,都是可散列的

如果是自定义对象,

需要支持下面三点:

(1) 支持 hash() 函数 (2) 支持通过 eq () 方法检测相等性 (3) 若 a==b 为真,则

hash(a)==hash(b) 也为真

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分