python中dict是什么意思_Python中的字典(dict)

字典这个数据结构活跃活跃在所有的Python程序背后,即使源码里没有直接用到他。

——《代码之美》

很久没写python的文章啦,这次讲一讲Python中很重要的模块,dict。这篇文章的内容主要包括:抽象mapping基类

字典的构造方法

字典中的细节和技巧

为什么字典的效率高——散列表的原理

抽象mapping基类

dict对象在python中属于mapping对象,且是目前仅有的一种标准映射类型。这类对象被定义为支持任意键查找并实现了Mapping或MutableMapping抽象基类中所规定方法的容器对象。而Mapping和MutableMapping则在collections.abc模块中被定义(python 3.2之后)。抽象基类的并不会实际被继承,而是会作为一个形式化文档,定义了构建某个类型所需要的最基本的接口。同时支持isinstance 方法来判断某个映射是否属于广义映射类型。例如:

>>> from collections.abc import Mapping

>>> a=dict()

>>> isinstance(a,Mapping)

True

>>>

Mapping类直接继承自Collections, 包含的方法包括:__contains__,keys,items,values,get,__eq__, and__ne__

MutableMapping 类则继承自Mapping类,除包含所有的Mapping类中的方法外,还包括:

pop,popitem,clear,update,和setdefault

字典的构造方法

字典可以通过花括号内包含的key: value对进行创建,例如:{4098:'jack',4127:'sjoerd'}。也可以通过dict构造器来创建。

dict 构造器的包括一个可选的位置参数和可以为空的关键字参数。位置参数可以为空,此时将创建一个空的字典,否则则需要是mapping类型或者iterable类型。构造器将首先根据位置参数创建一个字典,并在创建完成后将关键字参数中的关键字作为key,对应的值作为value加入到创建完成的字典中。

以下是几个例子:

不使用位置参数,直接使用关键字参数进行创建:

a = dict(one=1, two=2, three=3)

使用花括号进行创建:

b = {'one': 1, 'two': 2, 'three': 3}

使用可迭代类型zip进行创建:

c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))

使用可迭代类型list进行创建:

d = dict([('two', 2), ('one', 1), ('three', 3)])

使用映射类型dict进行创建:

e = dict({'three': 3, 'one': 1, 'two': 2})

以上5种方法生成的dict是相等的,同时需要注意,当位置参数为iterable对象时,每一项本身必须时恰好包含两个元素的iterable对象,如c, d的这两种生成方式。

同时,和list类似,dict本身也有字典推导的方法来生成,如果熟悉列表推导,这种方法就相当好理解,例如:

f={i:str(i) for i in range(10)}

字典中的细节和技巧

字典中键的顺序

在3.7 版本之后,字典类型将会保留插入的顺序,同时对键值的更新不会影响顺序。删除并再次添加的键将被插入到末尾。在之前的版本中则不保证顺序,不过可以使用OrderedDict.

如何判断两个字典是否相等

两个字典是否相等可以通过'=='比较,当且仅当他们具有完全相同的(键:值)时才成立,在比较的过程中不会考虑顺序。需要注意的是,在使用视图对象dict.values()进行相等性判断时,总是返回False,即使这两个values()来自同一个dict.

什么是字典视图

由dict.keys(), dict.values(), dict.items()返回的对象是视图对象,他们将分别返回键,值,(键,值)的视图。当字典改变时,视图也会发生相应改变。视图对象支持迭代,成员检测,但无法通过改变视图对象来操纵字典。

需要注意的是,在添加或删除字典中的条目期间对视图进行迭代可能引发

dict.keys()所返回的视图类似集合,抽象基类collections.abc.set中定义的所有操作都是有效的。例如:

>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}

>>> keys = dishes.keys()

>>> keys & {'eggs', 'bacon', 'salad'}

{'eggs','bacon'}

字典是可逆的吗

在3.8版本之后字典视图和字典都是可逆的,可以通过reversed关键字返回字典,字典视图的逆序。对字典进行逆序时,将返回键的逆序的迭代器。

从字典中删除项

使用 del d[key] 可以将d[key]从d中移除,如果d中不存在key时则会引发KeyError。

如果想要不返回KeyError则可以使用 pop(key [, default]),这个操作相比于del 不同在于会返回被删除的值,同时如果default被指定且key不存在d中时不会报错,而会返回default.

popitem()将从字典中删除一个(键,值)对,在python 3.7 之后的版本键值将按照LIFO的顺序进行返回,在之前的版本则会返回一个任意的键值对。

字典中的默认值

在字典中指定默认值可以减少插入时的查找次数,很多方法都可以指定默认值,例如:get(key[,default]), setdefault(key[,default]), pop(key[,default]) ,分别用于获取,设置,删除值,当key不存在且指定了default时,将不会返回KeyError,而是返回默认值。这可以使得在操作前不用提前判断key是否在dict中,从而减少一次查找。

同时,在自定义的映射类型中,也可以通过__missing__来设置默认值来处理找不到键的情况,这个方法更加灵活。

更新多个键值对

使用d[key]=value的方式可以更新一个键值对,如果想更新多个键值对则可以使用update函数,这个方法将更新另一个mapping对象或者dict对象中的所有键值对,或者使用关键字参数。

为什么字典的效率高——散列表的原理

字典和集合是python中出现次数非常高的数据结构,本身经过了高度的优化,主要基于散列表的方法。可以这样认为,如果程序包含磁盘I/O,则一个存储在内存中的任意大小的字典或集合的查询操作所需要的时间都是可以忽略不记的。

散列表本身是一个稀疏的数组,在dict中,每一个键值对都占用一个表元,表元大小一致,内部包含的是对键值的分别引用。表元的大小一致决定了散列表本身能够通过偏移量来读取某个表元。

Python会设法保证大概1/3的表元是空的,这样设计来保证散列表的冲突概率降低。即使有数百万个元素的dict,整个搜索平均的冲突次数可能仅有1-2次。当这个阈值到达时,原来的散列表会被复制到更大的空间里。这个复制的过程不保证顺序,所以当使用视图迭代时,可能会因为插入操作而改变顺序,导致部分值无法被遍历或者runtime error.

python 内置的hash()方法可以用于所有的内置类型对象,如果是自定义类型的话,这个过程调用的则是__hash__ 方法,如果两个对象在比较时是相等的,那么他们的hash值也需要是相等的。例如 hash(1)==hash(1.0) 即使这两个数字一个是整型一个是浮点型。这也表明,使用d[1], 和d[1.0]将返回的是同一个value.

如果一个类没有定义x.__hash__()会返回一个恰当的值以确保x==y同时意味着x is y且hash(x)==hash(y)

从Python 3.3开始str, bytes, datetime过程包含了加盐的步骤,所加的盐值是python进程中的一个常量,但每次启动python解释器都会生成不同的盐值。

由于字典使用了散列表,且保证了散列表的稀疏性,字典本身占用的空间较大,因此如果是数量巨大的记录,使用元组或者具名元组将占用更少的空间,这部分的优化主要用于生产环境。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值