python_字典1

字典_特点_4种创建方式_普通_dict_zip_formkeys

字典

  • 字典是“键值对”的无序可变序列,字典中的每一个元素都是一个“键值对”,包含:“键对象”和“值对象”。(即成对存在,每一个元素为一个二元组)可以通过“键对象”实现快速获取、删除、更新对应的“值对象”。
    注1:从数学上理解,它是二元组(键,值)的集合,是平面点集,只不过这里横纵坐标并不是简单的数字,键类似于identity,即地址;值类似于value,即值或者说是内容。

  • 列表中,我们通过下标数字找到对应的对象字典中通过键对象找到对应的值对象。“键”是任意的不可变数据(我这里理解为地址和值的关系,也即identityvalue的关系),比如:整数、浮点数、字符串、元组。但是,列表、集合、字典这些可变对象,不能作为“键”。并且“键”不可重复。

  • “值”可以是任何的数据,并且可重复

(注:键值对 ?既然是叫对,说明是成对存在。键和值链接在一起,类似于内存单元中一个地址链接着一个值)

一个典型的字典的定义方式:
a={‘name’:’liuan’,’age’:18,’job’:’CTO’}

(注:这是3个键值对,键:name、age、job。值:liuan、18、CTO)
见名知意,这其实就是我们生活中的(新华)字典。所以字典的关键字以dict为名,也即dictionary

注2:其实不管是编程语言还是一些数学教材,有很多符号都是根据英文单词来命名的,多查一查单词可以帮助我们来理解编程或者数学中的专业术语

字典的创建

  1. 我们可以通过 {}、dict() 来创建字典对象。
>>>a={‘name’:’liuan’,’age’:18,’job’:CTO}
>>>b=dict(name=’liuan’,age=18,job=’CTO’)
>>>a=dict([(‘name’,’liuan’),(‘age’,18)])
>>>c={}     #空的字典对象
>>>d=dict()     #空的字典对象
  1. 通过 zip() 创建字典对象
>>>k=[‘name’,’age’,’job’]
>>>v=[‘liuan’,18,’CTO’]
>>>d=dict(zip(k,v))
>>>d
{‘name’:’liuan’,’age’:18,’job’:’CTO’}
  1. 通过 fromkeys 创建值为空的字典
>>>a=dict.fromkeys([‘name’,’age’,’job’])
>>>a
{‘name‘:None,’age’:None,’job’:None}

字典元素的访问

为了测试各种访问方法,我们这里先设定一个字典对象(你当然可以设定为其他对象,比如你自己):
a={‘name’:’liuan’,’age’:18,’job’:’cto’}

  1. 通过 [键] 获得值。若键不存在,则抛出异常。
>>>a={‘name’:’liuan’,’age’:18,’job’:’cto’}
>>>a[‘name’]
‘liuan’
>>>a[‘age’]
18
>>>a[‘job’]
‘cto’
>>>a[‘sex’]
Error!
  1. 通过 get() 得到值,推荐使用。优点是:指定键不存在,返回None;也可以设定指定键不存在时默认返回的对象,推荐使用get()来获取“值对象”。
>>>a.get(‘name’)
‘liuan’
>>>a.get(‘sex’,’一个男孩’)
一个男孩
  1. 列出所有的键值对
>>>a.items()
dict_items([(‘name’,’liuan’),(‘age’,18),(‘job’,’cto’)])
  1. 列出所有的键,列出所有的值
>>>a.keys()
dict_keys([‘name’,’age’,’job’])
>>>a.values()
dict_values([‘liuan’,18,’cto’])
  1. len() 键值对的个数
  2. 检测一个“键”是否在字典对象中
>>>a={‘name’:liuan’,’age’:18}
>>>’name’	 in a
True

字典_元素的添加_修改_删除

  1. 给字典新增“键值对”。如果“键”已经存在,则覆盖旧的键值对。否则,则新增键值对。
>>>a={‘name’:’liuan’,’age’:18,’job’:’cto’}
>>>a[‘sex’]=’male’
>>>a[‘age’]=16
>>>a
{‘name’:’liuan’,’age’:16,’job’:’cto’,’sex’:’male’}
  1. 使用 update() 将新字典中所有键值对全部添加到旧字典对象上。如果key有重复,则直接覆盖。
>>>a={‘name’:’liuan’,’age’:18,’job’:’cto’}
>>>b={‘name’:’liuxiaoyi’,’money’:10,’sex’:’female’}
>>>a.update(b)
>>>a
{‘name’:’liuxiaoyi’,’age’:18,’job’:’cto’,’money’:10,’sex’:’female’}
  1. 字典中元素的删除,可以使用 del() 方法,或者clear()删除所有键值对; pop() 删除指定键值对,并返回对应的“值对象”
>>>a={‘name’:’liuan’,’age’:18,’job’:’cto’}
>>>del(a[‘name’])     #或者del a[‘name’]
>>>a
{‘age’:18,’job’:’cto’}
>>>b=a.pop(‘age’)
>>>b
18
  1. popitem() :随机删除和返回该键值对。字典是“无序可变序列”,因此没有第一个元素、最后一个元素一说。Popitem弹出随机的项,因为字典并没有最后一个元素等顺序的概念。若想一个接一个的移除并处理项,这个方法就非常有效。
>>>a={‘name’:’liuxiaoxiao’,’age’:18,’job’:’cto’}
>>>a.popitem()
(‘job’,’cto’)
>>>a.popitem()
(‘age’,18)
>>>a
{‘name’:’liuxiaoxiao’}

字典_序列解包用于列表元组字典

序列解包

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

>>>x,y,z=(20,10,30)
>>>x
20
>>>y
10
>>>z
30
>>>(a,b,c)=(1,2,3)
>>>a
1
>>>[a,b,c]=[10,20,30]
>>>a
10
  • 序列解包用于字典时,默认是对键进行操作;如果需要对键值对进行操作,则需要使用 items() ;如果需要对“值”进行操作,则需要使用 values();
>>>s={‘name’:’liuxiaoxiao’,’age’:18,’job’:’cto’}
>>>name,age,job=s     #默认对键进行操作
>>>name
‘name’
>>>name,age,job=s.items()     #对键值对进行操作
>>>name
(‘name’,’liuxiaoxiao’)
>>>name,age,job=s.values()     #对值对象进行操作
>>>name
‘liuxiaoxiao’

字典_复杂表格数据存储_列表和字典综合嵌套

见下面表格:

姓名年龄薪资城市
刘小小1830000北京
刘中中1920000上海
刘大大2010000深圳

Problem😗*请将该表格用字典或列表打出来:

源码:

>>>row1=dict(name='liuxiaoxiao',age=18,salary=30000,city='beijing')
>>>row2=dict(name='liuzhongzhong',age=19,salary=20000,city='shanghai')
>>>row3=dict(name='liudada',age=20,salary=10000,city='shenzhen')

>>>table=[row1,row2,row3]

#获得liuzhongzhong的薪资
>>>print(table[1]['salary'])
#或者table[1].get('salary')

#打印表的所有薪资
>>>for i in range(3):
        print(table[i]['salary'])

#打印表的所有数据
>>>for i in range(3):
        print(table[i]['name'],end='\t')
        print(table[i]['age'],end='\t')
        print(table[i]['salary'],end='\t')
        print(table[i]['city'],end='\t')
        print('\n')

方法不尽相同,还有下面方法:

list1=['姓名','年龄','薪资','城市']
list2=['刘小小',18,30000,'北京']
list3=['刘中中',19,20000,'上海']
list4=['刘大大',20,10000,'深圳']

table=[list1,list2,list3,list4]
for i in range(3):
    print(table[i+1][2])

table

字典_核心底层原理_内存分析_存储键值对过程

字典核心底层原理(❤❤❤)

  • 字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做bucket。每个bucket有两个部分:一个是键对象的引用,一个是值对象的引用。
    (我觉得其实还是 identity 和 value )
  • 由于,所有bucket结构和大小一致,我们可以通过偏移量来读取指定bucket

在这里插入图片描述

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

>>>a={}
>>>a[‘name’]=’liuxiaoxiao’

假设字典a创建完成后,数组长度为8:
在这里插入图片描述

我们要把’name’=‘liuxiaoxiao’这个键值对放进字典对象a中,首先第一步是需要计算键‘name’的散列值。Python中可以通过hash()来实现。

>>>bin(hash(‘name’))     #计算键‘name’的散列值,并转换为二进制数字
‘-0b1010111101001110110101100100101’

由于数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即‘101’,十进制数字是5。我们查看偏移量5,对应的bucket是否为空。如果为空,则将键值对放进去。如果不为空,则依次取右边3位作为偏移量,即‘100’,十进制数字是4。直到找到为空的bucket将键值对放进去。流程图如下:

在这里插入图片描述

(扩容:Python会根据散列表的拥挤程度扩容。“扩容”指:创造更大数组,将原有内容拷贝到新数组中。
接近2/3时,数组就会扩容。)

字典_核心底层原理_内存分析_查找值对象过程

根据键查找‘’键值对‘’的底层过程

前面我们明白了,一个键值对是如何存储到数组中的,根据键对象取到值对象,理解起来就简单了。

>>>a.get(‘name’)
‘liuxiaoxiao’

当我们调用a.get(‘name’)时,就是根据键’name’查找到“键值对”,从而找到值对象‘liuxiaoxiao’

第一步,我们仍然要计算’name’对象的散列值:

>>>bin(hash(‘name’))
‘-0b1010111101001110110101100100101’

和存储的底层流程算法一致,也是依次取散列值的不同位置的数字。假设数组长度为8,我们可以拿计算出来的散列值的最右边3位数字作为偏移量,即‘101’,十进制是5.我们查看偏移量5,对应的bucket是否为空。如果为空,则返回None。如果不为空,则将这个bucket的键对象计算其对应散列值,和我们的散列值进行比较,如果相等,则将对应“值对象”返回,如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后,仍然没有找到,则返回None。流程图如下:

在这里插入图片描述

总结

  1. 键必须可散列。
    数字、字符串、元组都是可散列的。
  2. 自定义对象需要支持下面三点:
    1. 支持hash()函数
    2. 支持通过_eq_()方法检测相等性
    3. 若a==b为真,则hash(a)==hash(b)为真
  3. 字典在内存中开销巨大,典型的空间换取时间
  4. 键查询速度快。
  5. 往字典里面添加新建可能导致扩容,导致散列表中键的次序发生变化。因此,不要在遍历字典的同时进行字典的修改。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值