python之字典

2021/12/30 1:08:00

本文主要是介绍python之字典,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前置疑问(对所学的疑问自己想知道什么)

Q1 字典有什么特点?
Q2 什么时候需要用到字典数据类型?
Q3 字典好像有键值对,具体有什么什么样子的?
Q4 字典如何在内存中存储的呢?是一块内存中分为两部分,一部分存储key,一部分存储value?
Q5 集合有并、交、差操作吗?


学习内容

1、字典的特点、创建、常见的操作方法、核心底层原理

2、集合的创建、常见的操作方法


学习时突发疑问

Q6 一个key 能对应多个value吗?一个value 能对应多个key吗?
我猜测key一对多value不行,但是多个键可以有同一个值,有点像数学中的函数 x与y的关系。可是意义不大啊。比如name 和 age 这个值明显不一样嘛。

Q7 满足什么条件才能作为键?


学习产出

1、字典

1.1 什么是字典

A1
字典是一个键/值对的集合,是无序的,且可变的。

1.2 创建字典的方式

A3

  • 基本语法创建{}
    {key:value}
>>> a = {'name':'xiaoming','age':20,'job':'programmer'}  #
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer'}
>>> type(a)
<class 'dict'>
  • dict()方法创建
>>> b = dict(name = 'xiaoming', age=18, job = 'programmer')
>>> b
{'name': 'xiaoming', 'age': 18, 'job': 'programmer'}
>>> type(b)
<class 'dict'>
  • zip()方法创建
>>> k = ['name','age','job']
>>> v = ['xiaoing',18,'programmer']
>>> c = dict(zip(k,v))
>>> c
{'name': 'xiaoing', 'age': 18, 'job': 'programmer'}
>>> type(c)
<class 'dict'>
  • fromkeys()方法创建
>>> d = dict.fromkeys(['name','age','job'])
>>> d
{'name': None, 'age': None, 'job': None}
>>> type(d)
<class 'dict'

还是{} 和dict() 方法创建简单

1.3 常见操作

1.3.1 访问
  • 通过键获得值,若键不存在,则报错
>>> a = {'name':'xiaoming','age':20,'job':'programmer'}
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer'}
>>> a['name']
'xiaoming'
>>> a['id']
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    a['id']
KeyError: 'id'
  • 通过get()方法来获得值
>>> a.get('name')
'xiaoming'
>>> a.get('age')
20

>>> a.get('id')			#不存在的i键 返回None
>>> a.get('id', 1234567) #可以指定返回内容
1234567
  • 列出所有的键值对
>>> a.items()
dict_items([('name', 'xiaoming'), ('age', 20), ('job', 'programmer')])
  • 列出所有的键、列出所有的值
>>> a.keys()
dict_keys(['name', 'age', 'job'])
>>> a.values()
dict_values(['xiaoming', 20, 'programmer'])
  • 键值个数(字典长度)
 >>> a.keys()
dict_keys(['name', 'age', 'job'])
>>> len(a)
3
  • 检测键是否存在字典中
>>> 'id' in a
False
>>> 'name' in a
True
1.3.2 增加、修改、删除
  • 直接添加
>>> a['id'] = 12345678
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer', 'id': 12345678}
  • 用update()方法更新原来的字典对象
>>> b = {'name': 'xiaoming', 'age': 20, 'job': 'programmer', 'id': 12345678, 'sex': 'man'}
>>>> a.update(b)
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer', 'id': 12345678, 'sex': 'man'}
  • del()方法删除
>>> del(a['sex'])
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer', 'id': 12345678}
  • pop()方法删除指定键值对
>>> a.pop('id')
12345678
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer'}
  • popitem()方法随机删除键值对
    因为字典是无序的
>>> a.popitem()
('test2', 'test2')
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer', 'test1': 'test1'}
  • clear()方法清除所有的键值对
>>> a1 = a
>>> a1
{'name': 'xiaoming', 'age': 20, 'job': 'programmer', 'test1': 'test1'}
>>> id(a1)
2239422203328
>>> id(a)
2239422203328
>>> a1.clear()
>>> a1
{}
>>> a
{}
1.3.3 序列解包 :a,b,c = x,y,z 这种格式
  • 键(默认) 返回的全是键
>>> a = {'name': 'xiaoming', 'age': 20, 'job': 'programmer'}
>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer'}
>>> name, age, job = a
>>> name
'name'
>>> age
'age'
>>> job
'job
  • 值 values() 返回的全是值
>>> name, age, job = a.values()
>>> name
'xiaoming'
>>> age
20
>>> job
'programmer'

键值对 items() 以键值对返回

>>> name, age, job = a.items()
>>> name
('name', 'xiaoming')
>>> age
('age', 20)
>>> job
('job', 'programmer')
>>> type(name) #注意返回的类型是元组
<class 'tuple'>
>>> type(age)
<class 'tuple'>
>>> type(job)
<class 'tuple'>

1.4 核心底层原理

A4

1.4.1 简述过程

字典对象的核心散列表(稀疏数组),数组的每个单元 叫做一个bucket,bucket 分为两部分 一个是key对象的地址,一个是值对象的地址。通过hash()方法存键取值,具体细节部分,如下。

1.4.2 存的过程

存的过程主要解决如何让这个key 放到对应的bucket索引中去,如图:
在这里插入图片描述
过程如下:

首先用hash()计算出key的散列值(二进制表示),然后从右往左依次取k位二进制,将这k位二进制转为十进制,记为i,如果i对应的bucket为空,则存放;如果不为空,再次向左侧取k位二进制。如果bucket满了,超过2/3时会自动扩容。
如何计算这个k呢?bucket为8时,k为3,bucket为16时,k为4。依次类推。

>>> a
{'name': 'xiaoming', 'age': 20, 'job': 'programmer'}
>>> bin(hash("name")) #计算出name的散列值,以二进制表示
'-0b1111001100101101011101101100100001110010100000110100011100110'

在这里插入图片描述

流程图如下:
在这里插入图片描述

那就有个疑问了,bucket的空间要是不是 2^k 怎么办呢? 还是说bucket默认创建的空间就是2^k 。会不会太浪费内存了呢?

我猜测这个内存默认开辟空间为2^k大小,且是根据实际自己电脑具体位数,来计算的。
比如我里面只有2个键值对,实际能存可能是能存放8个,如果是9个键值对,实际开辟的大小是16。
这字典是以空间换时间。读取数据快。

1.4.3 根据键取值的过程

当我们用get(“name”)找到对应的值时,首先还是会计算这个键的散列值,然后依然是从右向左取k位二进制数,转为十进制数位i,如果i位空,返回None;如果不为空,需要计算对应此时已经存储i索引的键的散列值,与当前的对象进行判断,如果相等,取出值;如果不相等,则向左再取k个二进制,进行计算,直到结束。

如图所示:
在这里插入图片描述
流程图:

在这里插入图片描述

A6

a = {"name":"xiaoming","name":"xiaohong","age":20}
>>> a
{'name': 'xiaohong', 'age': 20} # 键名称为name的只有一个。满足集合的特点。

A7
键必须是可散列的。
满足两个条件称为"可散列":
1、具有__hash__方法 ,可将一个类型映射为一个int值,且在一个生命周期中保持不变。
2、具有__eq__方法,能够判断两个对象是否相等。

2、集合

2.1 创建字典的方式

  • 基础语法创建{}
>>> a = {1,2,3,4,5,5,5,5}
>>> a
{1, 2, 3, 4, 5}
  • set()方法创建
    可将列表、元组转为集合
>>> a = set([1,2,3,4,5,5,5])
>>> a
{1, 2, 3, 4, 5}
>>> a = set((1,2,3,4,5,6,6,7,7,7))
>>> a
{1, 2, 3, 4, 5, 6, 7}

2.2 增 、删、并、交、差操作

  • 增 add()
>>> a
{1, 2, 3, 4, 5, 6, 7}
>>> 
>>> a.add(8)
>>> a
{1, 2, 3, 4, 5, 6, 7, 8}
  • 删 remove(), clear()
>>> a
{1, 2, 3, 4, 5, 6, 7, 8}
>>> a.remove(1)
>>> a
{2, 3, 4, 5, 6, 7, 8}
>>> a.clear()
>>> a
set()

A5

  • 并(|)union()、交(&)intersection()、差(-)difference()
>>> a = {1,2,3}
>>> b = {4,5,6}
>>> c = {1,2,3,4,5,6}
>>> a | b
{1, 2, 3, 4, 5, 6}
>>> a & b
set()
>>> a - b
{1, 2, 3}
>>> b - a
{4, 5, 6}
>>> a & c
{1, 2, 3}
>>> b & c
{4, 5, 6}

>>> a.union(b)
{1, 2, 3, 4, 5, 6}
>>> a.intersection(b)
set()
>>> a.difference(b)
{1, 2, 3}

2.3 集合的特点

无序、无重复、可变

3 列表、元组、字典、集合的区别

数据类型有序无序是否可变各自特点
列表有序可变像是升级的顺序表
元组有序不可变受到限制的列表
字典无序可变键值对,是特殊的集合,无重复元素
集合无序可变只有键,无值,无重复元素

今日代码

>>> a = [
	['xiaoming', 20, '20330801', 'm'],
	['xiaohong', 20, '20300802', 'f'],
	['xiaogang', 20, '20300803', 'm'],
	]
>>> a
[['xiaoming', 20, '20330801', 'm'], ['xiaohong', 20, '20300802', 'f'], ['xiaogang', 20, '20300803', 'm']]

>>> d1 = {"name":"xiaoming","age":20,"salary":30000,"location":"beijing"}
>>> d2 = {"name":"xiaohong","age":20,"salary":20000,"location":"shanghai"}
>>> d3 = {"name":"xiaogang","age":20,"salary":15000,"location":"hangzhou"}
>>> 
>>> td = [d1,d2,d3]
>>> td
[{'name': 'xiaoming', 'age': 20, 'salary': 30000, 'location': 'beijing'}, {'name': 'xiaohong', 'age': 20, 'salary': 20000, 'location': 'shanghai'}, {'name': 'xiaogang', 'age': 20, 'salary': 15000, 'location': 'hangzhou'}]


这篇关于python之字典的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程