Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
f173654d
Commit
f173654d
authored
Mar 23, 2009
by
Raymond Hettinger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Forward port r70533 and r70538.
parent
30364204
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
45 additions
and
32 deletions
+45
-32
Lib/collections.py
Lib/collections.py
+45
-32
No files found.
Lib/collections.py
View file @
f173654d
...
...
@@ -11,74 +11,87 @@ from operator import itemgetter as _itemgetter
from
keyword
import
iskeyword
as
_iskeyword
import
sys
as
_sys
import
heapq
as
_heapq
from
weakref
import
proxy
from
itertools
import
repeat
as
_repeat
,
chain
as
_chain
,
starmap
as
_starmap
################################################################################
### OrderedDict
################################################################################
class
_Link
(
object
):
__slots__
=
'prev'
,
'next'
,
'key'
,
'__weakref__'
class
OrderedDict
(
dict
,
MutableMapping
):
'Dictionary that remembers insertion order'
# The inherited dict maps keys to values.
# The internal self.__map dictionary maps keys to links in a doubly linked list.
# The doubly linked list starts and ends with a sentinel element.
# The sentinel element never gets deleted. It simplifies the algorithm.
# Setting a new item causes a new link to append to the doubly linked list.
# Deleting an item uses self.__map to find the link, which is then removed.
# Iteration follows the linked list in order.
# Reverse iteration follows the links backwards.
# An inherited dict maps keys to values.
# The inherited dict provides __getitem__, __len__, __contains__, and get.
# The remaining methods are order-aware.
# Big-Oh running times for all methods are the same as for regular dictionaries.
# Big-O running times for all methods are the same as for regular dictionaries.
# The internal self.__map dictionary maps keys to links in a doubly linked list.
# The circular doubly linked list starts and ends with a sentinel element.
# The sentinel element never gets deleted (this simplifies the algorithm).
# The prev/next links are weakref proxies (to prevent circular references).
# Individual links are kept alive by the hard reference in self.__map.
# Those hard references disappear when a key is deleted from an OrderedDict.
def
__init__
(
self
,
*
args
,
**
kwds
):
if
len
(
args
)
>
1
:
raise
TypeError
(
'expected at most 1 arguments, got %d'
%
len
(
args
))
try
:
self
.
__
end
self
.
__
root
except
AttributeError
:
self
.
__root
=
_Link
()
# sentinel node for the doubly linked list
self
.
clear
()
self
.
update
(
*
args
,
**
kwds
)
def
clear
(
self
):
self
.
__end
=
end
=
[]
end
+=
[
None
,
end
,
end
]
# sentinel node for doubly linked lis
t
self
.
__map
=
{}
# key --> [key, prev, next]
root
=
self
.
__root
root
.
prev
=
root
.
next
=
roo
t
self
.
__map
=
{}
dict
.
clear
(
self
)
def
__setitem__
(
self
,
key
,
value
):
# Setting a new item creates a new link which goes at the end of the linked
# list, and the inherited dictionary is updated with the new key/value pair.
if
key
not
in
self
:
end
=
self
.
__end
curr
=
end
[
1
]
curr
[
2
]
=
end
[
1
]
=
self
.
__map
[
key
]
=
[
key
,
curr
,
end
]
self
.
__map
[
key
]
=
link
=
_Link
()
root
=
self
.
__root
last
=
root
.
prev
link
.
prev
,
link
.
next
,
link
.
key
=
last
,
root
,
key
last
.
next
=
root
.
prev
=
proxy
(
link
)
dict
.
__setitem__
(
self
,
key
,
value
)
def
__delitem__
(
self
,
key
):
# Deleting an existing item uses self.__map to find the link which is
# then removed by updating the links in the predecessor and successor nodes.
dict
.
__delitem__
(
self
,
key
)
key
,
prev
,
next
=
self
.
__map
.
pop
(
key
)
prev
[
2
]
=
next
next
[
1
]
=
prev
link
=
self
.
__map
.
pop
(
key
)
link
.
prev
.
next
=
link
.
next
link
.
next
.
prev
=
link
.
prev
def
__iter__
(
self
):
end
=
self
.
__end
curr
=
end
[
2
]
# start at first link
while
curr
is
not
end
:
yield
curr
[
0
]
# yield KEY for each link
curr
=
curr
[
2
]
# goto next link
# Traverse the linked list in order.
root
=
self
.
__root
curr
=
root
.
next
while
curr
is
not
root
:
yield
curr
.
key
curr
=
curr
.
next
def
__reversed__
(
self
):
end
=
self
.
__end
curr
=
end
[
1
]
# start at last link
while
curr
is
not
end
:
yield
curr
[
0
]
# yield KEY for each link
curr
=
curr
[
1
]
# goto prev link
# Traverse the linked list in reverse order.
root
=
self
.
__root
curr
=
root
.
prev
while
curr
is
not
root
:
yield
curr
.
key
curr
=
curr
.
prev
def
__reduce__
(
self
):
items
=
[[
k
,
self
[
k
]]
for
k
in
self
]
tmp
=
self
.
__map
,
self
.
__
end
del
self
.
__map
,
self
.
__
end
tmp
=
self
.
__map
,
self
.
__
root
del
self
.
__map
,
self
.
__
root
inst_dict
=
vars
(
self
).
copy
()
self
.
__map
,
self
.
__
end
=
tmp
self
.
__map
,
self
.
__
root
=
tmp
if
inst_dict
:
return
(
self
.
__class__
,
(
items
,),
inst_dict
)
return
self
.
__class__
,
(
items
,)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment