您的位置:首页 > 编程语言 > Python开发

python 字典详解 一 (基础用法)

2016-03-07 10:08 811 查看
python字典是python中非常重要的一个基础类型,它是一个高效的基础类型,不仅在编写程序的时候经常用到,就连python底层的实现都大量的使用了字典。

主要从几个方面去学习python的字典

1. 字典的基本使用
2. 字典的扩展和针对它的一些类库(针对特殊用途的字典)
3. 自定义自己的字典
4. 字典的底层实现


字典的基本使用

创建字典

创建字典有很多种方式,但是要注意一点的是,字典的键必需是能够哈希的,因此字典的键的哈希值应该在对象的生命周期中是不会变的,这其中包括不可变类型如:str, bytes, int,还有frozen set, 和不包含可变类型项的元组,以及实现了eq()和hash()方法的hash值不变的对象。

下面列举了一些构造字典的方法

(只考虑方法,并未关注效率问题, 关于效率问题在深入研究之后来分析)

直接构造字典的方式

a = {‘one’ : 1, ‘two’ : 2, ‘three’ : 3}

通过工厂方法创建字典

传字典参数的方法构造字典:

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

使用zip方法构造

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

元组对列表的方式

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

直接以字典作为构造参数的形式

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

列表对元组的方式

f = dict(([‘one’, 1], [‘two’,2],[‘three’,3]))

fromkeys创建默认值字典:

g = dict.fromkeys([‘one’,’tow’,’three’], 1)

字典推导式

h = {value:index+1 for index, value in  enumerate(['one','tow','three'])}


可见python中的字典是非常强大的,它的操作非常丰富和方便,下面列举一些常用的操作

常用操作

字典中有哪些方法,怎么使用了

首先来看下字典的类图



dict_test = {1: ‘one’, 2: ‘two’, 3: ‘three’}

container

可以使用 in 来判断元素是否存在:

>>> 1 in dict_test


True

mapping

>>> dict_test.keys()
dict_keys([1, 2, 3])
>>> dict_test.values()
dict_values(['one', 'two', 'three'])
>>> dict_test.items()
dict_items([(1, 'one'), (2, 'two'), (3, 'three')])


注: 在python3中这三个方法返回的都是视图,

另外可以通过key取得值

>>> dict_test[1]


‘one’

也可以直接给key配对值

>>> dict_test[4] = 'four'

>>> dict_test


{1: ‘one’, 2: ‘two’, 3: ‘three’, 4: ‘four’}

以及使用get方法取得值,如果没有这个key返回默认值

>>> dict_test.get(1, '1')


‘one’

>>> dict_test.get('1', '1')


‘1’

sized

获取字典的长度

>>> len(dict_test)


3

iterable

可以遍历和是迭代对象(以键进行遍历)

>>> for value in dict_test:
...     print(value)
...


1

2

3

>>> from collections import Iterable
>>> isinstance(dict_test, Iterable)


True

>>> iter(dict_test)


iterator

变成迭代器

>>> iter_test = iter(dict_test)
>>> next(iter_test)


1

>>> next(iter_test)


2

>>> next(iter_test)


3

>>> next(iter_test)


Traceback (most recent call last):

File “”, line 1, in

StopIteration

其他一些方法

>>> dir(dict_test)


['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__
', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__s
tr__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']


常用的方法

pop 移除并返回移除的键对应的值, 需要传一个key参数

>>> dict_test.pop(1)


‘one’

>>> dict_test


{2: ‘two’, 3: ‘three’}

同上, popitem移除并返回移除的键值对

>>> dict_test.popitem()


(2, ‘two’)

>>> dict_test


{3: ‘three’}

setdefault 方法类似于get方法,只不过在没有找到键的情况下会将这个键对应的值设置成默认值,并将这个值返回,如果有这个键,直接返回键对应的值

>>> dict_test.setdefault(4, 'four')


‘four’

>>> dict_test


{1: ‘one’, 2: ‘two’, 3: ‘three’, 4: ‘four’}

直接删除字典中的键值对

>>> del dict_test[1]
>>> dict_test


{2: ‘two’, 3: ‘three’, 4: ‘four’}

copy方法, 直接调用copy()为浅拷贝, 即创建了一个新对象,但内容实际上是用的原对象内容的引用, 请看下面的这个例子

>>> dict_test =  {'one':1, 'two':[1,1]}
>>> dict_copy = dict_test.copy()
>>> dict_copy['two'].append(1)
>>> dict_test['two']


[1, 1, 1]

使用深拷贝就不会有这个问题

dict_test =  {'one':1, 'two':[1,1]}
import copy
dict_deep_copy = copy.deepcopy(dict_test)


dict_deep_copy['two'].append(1)


dict_test['two']


[1, 1]

部分方法前面已经有演示了,这里不再说明, update用于字典合并,合并有很多种方法,而且经常用到,

合并和更新字典

这里列举一些方法:

dict1 = dict([(1,'one'), (2,'two')])
dict2 = {2:'two_two',3:'three'}


直接用update方法(这种情况会改变字典)

>>> dict1.update(dict2)
>>> dict1


{1: ‘one’, 2: ‘two_two’, 3: ‘three’}

可以使用copy方法或者工厂方法,新创建一个字典从而不改变原有字典

>>> dict1_copy = dict1.copy() # dict(dict1)
>>> dict1_copy.update(dict2)
>>> dict1_copy


{1: ‘one’, 2: ‘two_two’, 3: ‘three’}

>>> dict1


{1: ‘one’, 2: ‘two’}

使用解绑再组合的方式,这种方式存在一些问题,如下:

>>> dict(dict1, **dict2)


Traceback (most recent call last):

File “”, line 1, in

TypeError: keyword arguments must be strings

因此这种方式只适合key为可作为变量名字的情况

同样可以使用字典推导式的方式进行字典合并

>>> {key:value for d in [dict1, dict2] for key, value in d.items()}


{1: ‘one’, 2: ‘two_two’, 3: ‘three’}

全部遍历相加的方法,类似于前面的推导式

>>> dict(list(dict1.items()) + list(dict2.items()))


{1: ‘one’, 2: ‘two_two’, 3: ‘three’}

使用连接操作符 ‘|’

>>> dict(dict1.items() | dict2.items())


{1: ‘one’, 2: ‘two’, 3: ‘three’}

>>> dict(dict2.items()|dict1.items())


{1: ‘one’, 2: ‘two_two’, 3: ‘three’}

这里覆盖的顺序变了, 如果有重复的key将以第一个字典中key的值作为最终合并的值

借助于其他类库

>>> from itertools import chain
>>> dict(chain(dict1.items(), dict2.items()))


{1: ‘one’, 2: ‘two_two’, 3: ‘three’}

>>> from collections import ChainMap
>>> ChainMap({}, dict2 ,dict1 )


ChainMap({}, {1: ‘one’, 2: ‘two’}, {2: ‘two_two’, 3: ‘three’})

>>> dict(ChainMap({}, dict1, dict2))


{1: ‘one’, 2: ‘two’, 3: ‘three’}

这里第一个空字典,是为了不改变dict1中的值, 而且注意字典的排放顺序, dict1需要放到最后,因为我们需要dict2中的值覆盖dict1中的值, 这种方式不进行字典遍历,因为它首先生成了一个view,在查找的时候才会去匹配,ChainMap并不会直接变成 dict, 需要dict工厂方法进行转换, 这种情况适合合并多个字典的情况

dict3 = {3:'three_three', 4:'four'}
>>> dict(ChainMap({}, dict3, dict2, dict1))


{1: ‘one’, 2: ‘two_two’, 3: ‘three_three’, 4: ‘four’}

注意字典在参数中的位置, 需要更新的字典放最后

全部解绑的方式(这种方便快捷的方式只在python3.5以上有效)

>>> {**dict1, **dict2}


{1: ‘one’, 2: ‘two_two’, 3: ‘three’}

除了合并比较两个字典的大小也常用

比较字典

由于在python2.1之后有增加了更加丰富的比较符, 但python2又一直保留着cmp这个内置函数,因此可以直接通过cmp方法进行比较但是在python3中这个内置方法已经移除,需要自己去实现那些比较符对应的方法,比如 < 对应着 _lt_, 其他类似: <= _le_, == _eq_, != _ne_, > _gt_, >= _ge_.

字典的比较顺序,在python2中遵守下面的规则

首先比较字典的长度, 然后比较字典的键,最后比较字典的值



而在python3中需要自己去实现那些比较符方法

dict1 = {1:'one', 3:'three'}
dict2 = {2:'two', 3:'three_three'}


condition = True if dict1 >= dict2 else False
condition


---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-26-6e55c3e20291> in <module>()
----> 1 condition = True if dict1 >= dict2 else False
2 condition

TypeError: unorderable types: dict() >= dict()


dict1.__lt__(dict2)


NotImplemented


另外要说的一点就是, 字典中的键是无序的集合,因此可以利用集合的一些操作来处理字典, 比如找到第一个字典中没有的键值对,可以利用集合的差补来做

{key: dict1[key] for key in set(dict1) - set(dict2)}


{1: ‘one’}

还有其他一些字典的操作,比如给字典排序, 扩展和改造自己的字典类型等,下次有时间总结下。

上面这些例子是在python3.4.3下面测试的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: