python dict update 源码_Python中OrderedDict源码剖析

最近刚好看了一下LRU的实现,其中使用了OrderedDict的数据结构,于是顺便读了一下源码总结一下当做自己的一个笔记(其实就是翻译一下源码中的注释)。

我们知道Dict中的数据并没有按照固定的顺序进行保存,每次对A={**kwds}使用A.item()进行遍历时的元素的遍历顺序都不同。OrderedDict实现了对一个字典的按照其key的添加顺序进行有序遍历以及常数复杂度的增删查改。

当然为dict数据结构实现固定的序列也要复出相应的代价,这是一种相比dict需要更大的存储空间的数据结构。

其主要原理如下:

首先在初始化时,需要生成:

1.与dict相同的字典(就暂时叫它self_dict吧),其key、value即为OrderedDict的key,value;

2.一个双向环形链表,存在一个哨兵节点root,节点value为数据的key;

3.另一个dict()(就暂时叫它map_dict吧),其key,value分别为OrderedDict的key以及该key在上述双向联邦中关联节点的引用。

下面就是初始化的源码了

def __init__(self, other=(), /, **kwds):

'''Initialize an ordered dictionary. The signature is the same asregular dictionaries. Keyword argument order is preserved.'''

try:

self.__root

except AttributeError:

self.__hardroot = _Link()

self.__root = root = _proxy(self.__hardroot)

root.prev = root.next = root # 利用哨兵节点root初始化双向环状链表

self.__map = {} # 初始化map_dict

self.__update(other, **kwds) # 初始化self_dict,self本身继承自dict类

以实例odict = Ordereddict(data)为例, 对增删查改的实现简单介绍一下。

在执行odict[key]=value进行节点插入/改动时,

1.判断key在self_dict中是否存在,存在的话只需要执行self_dict[key] = value即可;

2.当key不存在,需要执行self_dict[key] = value,并在双向环形链表的末尾(即哨兵节点前一个节点)插入lastnode = node(prev=root.prev, next=root,value=key),并在map_dict中加入map_dict[key]=lastnode。

其__setitem__方法实现如下:

def __setitem__(self, key, value,

dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):

'od.__setitem__(i, y) <==> od[i]=y'

# Setting a new item creates a new link at the end of the linked list,

# and the inherited dictionary is updated with the new key/value pair.

if key not in self: # 2.key值不存在的情况。

self.__map[key] = link = Link() # 更新map_dict

root = self.__root # 更新双向链表

last = root.prev

link.prev, link.next, link.key = last, root, key

last.next = link

root.prev = proxy(link)

dict_setitem(self, key, value) # 1.key值存在 只更新value 不更新插入顺序

其中增删查改的时间复杂度都为常数(注:对链表进行查找是通过dict_map实现的,而非遍历),空间复杂度比dict多了一个等长的双向链表以及一个额外的字典。

其实到这一步,基本上就对OrderedDict的原理介绍的差不多了,其他方法的实现相对而言也比较容易想到,感兴趣的话可以去找源码了解一下。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值