提交 75464f23 authored 作者: Frederic's avatar Frederic

Make OrderedSet pickable in more cases, by doing manual weakref.

Why do it use weakref anyway for the Link?
上级 ba2727e7
...@@ -41,21 +41,16 @@ if MutableSet is not None: ...@@ -41,21 +41,16 @@ if MutableSet is not None:
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## {{{ http://code.activestate.com/recipes/576696/ (r5) ## {{{ http://code.activestate.com/recipes/576696/ (r5)
import collections import collections
from weakref import proxy
import weakref import weakref
class Link(object): class Link(object):
__slots__ = 'prev', 'next', 'key', '__weakref__' __slots__ = 'prev', 'next', 'key', '__weakref__'
def __getstate__(self): def __getstate__(self):
# The proxy aren't pickled by default. # weakref.proxy don't pickle well, so we use weakref.ref
# We want to restore them. # manually and don't pickle the weakref.
# The way we restore the proxy we create more # We restore the weakref when we unpickle.
# proxy, but we do not care. ret = [self.prev(), self.next()]
ret = [self.prev, self.next,
isinstance(self.prev, weakref.ProxyType),
isinstance(self.next, weakref.ProxyType),
]
try: try:
ret.append(self.key) ret.append(self.key)
except AttributeError: except AttributeError:
...@@ -63,16 +58,10 @@ if MutableSet is not None: ...@@ -63,16 +58,10 @@ if MutableSet is not None:
return ret return ret
def __setstate__(self, state): def __setstate__(self, state):
if state[2]: self.prev = weakref.ref(state[0])
self.prev = proxy(state[0]) self.next = weakref.ref(state[1])
else: if len(state) == 3:
self.prev = state[0] self.key = state[2]
if state[3]:
self.next = proxy(state[1])
else:
self.next = state[1]
if len(state) == 5:
self.key = state[4]
class OrderedSet(collections.MutableSet): class OrderedSet(collections.MutableSet):
'Set the remembers the order elements were added' 'Set the remembers the order elements were added'
...@@ -94,7 +83,7 @@ if MutableSet is not None: ...@@ -94,7 +83,7 @@ if MutableSet is not None:
# Checks added by IG # Checks added by IG
check_deterministic(iterable) check_deterministic(iterable)
self.__root = root = Link() # sentinel node for doubly linked list self.__root = root = Link() # sentinel node for doubly linked list
root.prev = root.next = root root.prev = root.next = weakref.ref(root)
self.__map = {} # key --> link self.__map = {} # key --> link
if iterable is not None: if iterable is not None:
self |= iterable self |= iterable
...@@ -111,8 +100,8 @@ if MutableSet is not None: ...@@ -111,8 +100,8 @@ if MutableSet is not None:
self.__map[key] = link = Link() self.__map[key] = link = Link()
root = self.__root root = self.__root
last = root.prev last = root.prev
link.prev, link.next, link.key = last, root, key link.prev, link.next, link.key = last, weakref.ref(root), key
last.next = root.prev = proxy(link) last().next = root.prev = weakref.ref(link)
def union(self, s): def union(self, s):
check_deterministic(s) check_deterministic(s)
...@@ -148,24 +137,24 @@ if MutableSet is not None: ...@@ -148,24 +137,24 @@ if MutableSet is not None:
# then removed by updating the links in the predecessor and successors. # then removed by updating the links in the predecessor and successors.
if key in self.__map: if key in self.__map:
link = self.__map.pop(key) link = self.__map.pop(key)
link.prev.next = link.next link.prev().next = link.next
link.next.prev = link.prev link.next().prev = link.prev
def __iter__(self): def __iter__(self):
# Traverse the linked list in order. # Traverse the linked list in order.
root = self.__root root = self.__root
curr = root.next curr = root.next()
while curr is not root: while curr is not root:
yield curr.key yield curr.key
curr = curr.next curr = curr.next()
def __reversed__(self): def __reversed__(self):
# Traverse the linked list in reverse order. # Traverse the linked list in reverse order.
root = self.__root root = self.__root
curr = root.prev curr = root.prev()
while curr is not root: while curr is not root:
yield curr.key yield curr.key
curr = curr.prev curr = curr.prev()
def pop(self, last=True): def pop(self, last=True):
if not self: if not self:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论