【导语】:本文介绍了Bi-Dictionary 库,即“Bi-directional Dictionary”双向字典,顾名思义,该库基于Python中的字典增加了由“值”访问键的功能,开发者可以通过值来反向查找键,使得处理字典更加方便。同时,该库也引起了 Python 之父 Guido 的注意,因此,很有必须学习Bi-Dictionary 库。
简介
字典是Python中最常见的数据结构之一,在日常开发中使用的频率很高。字典由一些键值对构成,我们只能通过键访问值,但是无法通过值访问键。目前有一个第三方库很好的解决了这个问题 - Bi-Dictionary,通过使用它,我们可以由值访问键。该库甚至引起了 Python 之父 Guido 的注意,因此这一特性未来可能会被加入到Python语法中。
安装
我们可以使用pip安装bidict库:
pip install bidict
随后,需要导入该库才能使用:
from bidict import bidict
简单使用
初步使用
我们首先通过创建一个字典,该字典的键为国家的简称,值为国家的全名,再用bidict初始化这个字典:
country_abbr_bidict = bidict({'USA': 'The United States of America'})
这样,我们只需要使用inverse()方法,就可以通过国家全称获取国家简称了:
from bidict import bidict country_abbr_bidict = bidict({'USA': 'The United States of America'}) shortName = country_abbr_bidict.inverse['The United States of America'] print(shortName)
结果为:USA
我们可以对比下原字典和反转后的区别:
from bidict import bidict country_abbr_bidict = bidict({'USA': 'The United States of America'}) print(country_abbr_bidict) print(country_abbr_bidict.inverse)
结果显示,inverse()方法反转了原字典的键值位置:
bidict({'USA': 'The United States of America'}) bidict({'The United States of America': 'USA'})
为何不使用Python的字典呢?
我们也可以在字典中把键值互换,再存储一份数据,这样也能实现与bidict相同的效果。我们来尝试一下:
country_abbr_dict = { 'USA': 'The United States of America', 'The United States of America': 'USA' }
如果我们想把USA更新成US,可以使用update()方法,像下面这样:
country_abbr_dict.update({ 'US': 'The United States of America', 'The United States of America': 'US' })
这似乎看起来很完美,但是字典仍然保留了原来的数据:
from bidict import bidict country_abbr_dict = { 'USA': 'The United States of America', 'The United States of America': 'USA' } country_abbr_dict.update({ 'US': 'The United States of America', 'The United States of America': 'US' }) print(country_abbr_dict)
在结果中我们可以看到USA也在字典中:
{'USA': 'The United States of America', 'The United States of America': 'US', 'US': 'The United States of America'}
为了避免这个问题,只能定义一个函数:
def update(d, key, val): oldval = d.pop(key, object()) d.pop(oldval, None) oldkey = d.pop(val, object()) d.pop(oldkey, None) d.update({key: val, val: key}) country_abbr_dict = { 'USA': 'The United States of America', 'The United States of America': 'USA' } update(country_abbr_dict, 'US', 'The United States of America') print(country_abbr_dict)
这样就可以成功更新字典了:
{'US': 'The United States of America', 'The United States of America': 'US'}
如果使用Bidict,就非常简单了:
country_abbr_bidict.inverse['The United States of America'] = 'US' print(country_abbr_bidict)
bidict({'US': 'The United States of America'})
Bidict用起来,明显更方便!
Bidict的其他用途
在查找值之前,传入默认值
Bidict继承了Python字典中的大部分特性。例如,当我们想要通过键访问bidict中的某个值时,可以传入一个默认值。这样,如果bidict中没有该值,就会将默认值作为结果返回。
from bidict import bidict country_abbr_bidict = bidict({ 'US': 'The United States of America', }) print(country_abbr_bidict.get('AU', 'Australia'))
结果就是我们传入的默认值:Australia
加入新的键值对
Bidict加入新键值对的方式与Python的原生字典一样,我们来试试:
from bidict import bidict country_abbr_bidict = bidict({ 'US': 'The United States of America', }) country_abbr_bidict['AU'] = 'Australia' country_abbr_bidict['CA'] = 'Canada' print(country_abbr_bidict)
结果为:
bidict({'US': 'The United States of America', 'AU': 'Australia', 'CA': 'Canada'})
检验Bidict中是否有某个特定值
(1)我们可以使用in关键字来检查Bidict中是否有CA:
'CA' in country_abbr_bidict
我们可以得到一个布尔值,表示该键是否存在于Bidict中:True
(2)同样我们也可以检查Bidict中是否有某个值,
'Australia' in country_abbr_bidict.inverse
结果显示Bidict中有该值:True
Pop and Delete方法
除了上述特性外,我们还可以使用Pop and Delete方法。
(1)pop()方法可以从Bidict中弹出键值对
country_abbr_bidict.pop('AU')
会返回该键对应的值:Australia
我们再看看Bidict:country_abbr_bidict
发现里面没有AU这个键值对了:bidict({'US': 'The United States of America', 'CA': 'Canada'})
(2)delete()方法可以通过键或者值的方式删除键值对
del country_abbr_bidict.inverse['Canada'] print(country_abbr_bidict)
结果显示删除成功:bidict({'US': 'The United States of America'})
约束
Python的设计理念是当程序出现错误时,一定要显示出来,Bidict的设计也遵循了这一点。Bidict的一个约束是键、值都要唯一,这是因为值也有可能会被当作键使用。因此,当我们想在Bidict中加入一个新的键值对(该键值对的值已经被其他键使用),就会报错。例如,我们想把US - The United States of America加入Bidict中,但是原字典中已有USA - The United States of America了:
from bidict import bidict country_abbr_bidict = bidict({ 'USA': 'The United States of America', }) country_abbr_bidict['US'] = 'The United States of America'
会产生如下错误:
Traceback (most recent call last): File "F:/Documents/其他资料/pythonprojects/01practice/app.py", line 5, incountry_abbr_bidict['US'] = 'The United States of America' File "F:pythonlibsite-packagesidict\_bidict.py", line 67, in __setitem__ self.put(key, val, on_dup=self.on_dup) File "F:pythonlibsite-packagesidict\_bidict.py", line 93, in put self._update([(key, val)], on_dup=on_dup) File "F:pythonlibsite-packagesidict\_base.py", line 455, in _update dedup_result = self._dedup(key, val, on_dup) File "F:pythonlibsite-packagesidict\_base.py", line 350, in _dedup raise ValueDuplicationError(val) bidict.ValueDuplicationError: The United States of America
我们可以使用forceput()方法来避免这一错误:country_abbr_bidict.forceput('USA', 'The United States of America')
但是,如果出现了两个键的值相同这种情况,该方法会把原来的键覆盖:bidict({'US': 'The United States of America'})
其他特性
更新多个键值对
putall()方法可以同时加入多个键值对到Bidict中,但传入的参数必须是可迭代的。
country_abbr_bidict.putall([ ('AU', 'Australia'), ('CA', 'Canada') ]) print(country_abbr_bidict)
结果显示加入成功:bidict({'USA': 'The United States of America', 'AU': 'Australia', 'CA': 'Canada'})
当某个键值对无法传入时,那么其他键值对也无法传入:
country_abbr_bidict = bidict({'US': 'United States of America'}) country_abbr_bidict.putall([ ('AU', 'Australia'), ('CA', 'Canada'), ('US', 'The United States of America') ])
这里出现了报错:
Traceback (most recent call last): File "F:/Documents/其他资料/pythonprojects/01practice/app.py", line 3, incountry_abbr_bidict.putall([ File "F:pythonlibsite-packagesidict\_bidict.py", line 179, in putall self._update(items, on_dup=on_dup) File "F:pythonlibsite-packagesidict\_base.py", line 443, in _update target._update(arg, kw, rbof=False, on_dup=on_dup) File "F:pythonlibsite-packagesidict\_base.py", line 455, in _update dedup_result = self._dedup(key, val, on_dup) File "F:pythonlibsite-packagesidict\_base.py", line 343, in _dedup raise KeyDuplicationError(key) bidict.KeyDuplicationError: US
而其他键值对也没有传入到Bidict中:bidict({'US': 'United States of America'})
forceupdate()方法的优先级
如果我们想使用该方法传入多个键值对,对Bidict进行更新,那么就要注意传入数据的先后顺序了。
如果把USA放到最后,那么最终Bidict就会使用该键:
country_abbr_bidict = bidict({'US': 'United States of America'}) country_abbr_bidict.forceupdate([ ('US', 'The United States of America'), ('USA', 'The United States of America') ])
结果为:bidict({'USA': 'The United States of America'})
如果把US放到最后,那么字典就会将US作为键。
country_abbr_bidict.forceupdate([ ('USA', 'The United States of America'), ('US', 'The United States of America') ]) print(country_abbr_bidict)
结果为:bidict({'US': 'The United States of America'})
与其他数据结构交互
Bidict可以转换为其他数据结构,反之亦然。例如,我们可以把Bidict转换为字典:dict(country_abbr_bidict)
结果为:{'US': 'United States of America'}
我们再把字典转换为Bidict: bidict(dict(country_abbr_bidict))
结果为:bidict({'US': 'United States of America'})
结论
在本文中,我介绍了Bi-Dictionary库-双向字典,也称为Bidict。它不仅改进了Python字典的缺点,而且遵循了Python的设计原则。非常值得学习!
全部0条评论
快来发表一下你的评论吧 !