提交 3dcaac82 authored 作者: nouiz's avatar nouiz

Merge pull request #1118 from delallea/python24

A few improvements to OrderedSet implementation
...@@ -141,7 +141,7 @@ def _contains_cycle(fgraph, orderings): ...@@ -141,7 +141,7 @@ def _contains_cycle(fgraph, orderings):
# IG: I tried using a shared empty_list = [] constructed # IG: I tried using a shared empty_list = [] constructed
# outside of the for loop to avoid constructing multiple # outside of the for loop to avoid constructing multiple
# lists, but this was not any faster. # lists, but this was not any faster.
parents.extend(orderings.get(a_n,[])) parents.extend(orderings.get(a_n, []))
if parents: if parents:
for parent in parents: for parent in parents:
...@@ -982,8 +982,8 @@ class DestroyHandler(toolbox.Bookkeeper): ...@@ -982,8 +982,8 @@ class DestroyHandler(toolbox.Bookkeeper):
# depend on destroyed_input # depend on destroyed_input
root_clients = OrderedSet() root_clients = OrderedSet()
for r in root_impact: for r in root_impact:
assert not [a for a,c in self.clients[r].items() if not c] assert not [a for a, c in self.clients[r].items() if not c]
root_clients.update([a for a,c in self.clients[r].items() if c]) root_clients.update([a for a, c in self.clients[r].items() if c])
root_clients.remove(app) root_clients.remove(app)
if root_clients: if root_clients:
rval[app] = root_clients rval[app] = root_clients
......
...@@ -15,7 +15,8 @@ def check_deterministic(iterable): ...@@ -15,7 +15,8 @@ def check_deterministic(iterable):
# So I must use an assert here. In the long term we should fix the rest of # So I must use an assert here. In the long term we should fix the rest of
# theano to use exceptions correctly, so that this can be a TypeError. # theano to use exceptions correctly, so that this can be a TypeError.
if iterable is not None: if iterable is not None:
assert isinstance(iterable, (list, tuple, OrderedSet, types.GeneratorType)) assert isinstance(iterable, (
list, tuple, OrderedSet, types.GeneratorType, basestring))
if MutableSet is not None: if MutableSet is not None:
# From http://code.activestate.com/recipes/576694/ # From http://code.activestate.com/recipes/576694/
...@@ -106,9 +107,21 @@ if MutableSet is not None: ...@@ -106,9 +107,21 @@ if MutableSet is not None:
return '%s(%r)' % (self.__class__.__name__, list(self)) return '%s(%r)' % (self.__class__.__name__, list(self))
def __eq__(self, other): def __eq__(self, other):
# Note that we implement only the comparison to another
# `OrderedSet`, and not to a regular `set`, because otherwise we
# could have a non-symmetric equality relation like:
# my_ordered_set == my_set and my_set != my_ordered_set
if isinstance(other, OrderedSet): if isinstance(other, OrderedSet):
return len(self) == len(other) and list(self) == list(other) return len(self) == len(other) and list(self) == list(other)
return set(self) == set(other) elif isinstance(other, set):
# Raise exception to avoid confusion.
raise TypeError(
'Cannot compare an `OrderedSet` to a `set` because '
'this comparison cannot be made symmetric: please '
'manually cast your `OrderedSet` into `set` before '
'performing this comparison.')
else:
return NotImplemented
def __del__(self): def __del__(self):
self.clear() # remove circular references self.clear() # remove circular references
...@@ -149,7 +162,7 @@ else: ...@@ -149,7 +162,7 @@ else:
raise KeyError(key) raise KeyError(key)
def __iter__(self): def __iter__(self):
return self.data.keys().__iter__() return self.data.__iter__()
def __reversed__(self): def __reversed__(self):
return self.data.__reversed__() return self.data.__reversed__()
...@@ -158,18 +171,32 @@ else: ...@@ -158,18 +171,32 @@ else:
raise NotImplementedError() raise NotImplementedError()
def __eq__(self, other): def __eq__(self, other):
return type(self) == type(other) and \ # Note that we implement only the comparison to another
self.data == other.data # `OrderedSet`, and not to a regular `set`, because otherwise we
# could have a non-symmetric equality relation like:
def __del__(self): # my_ordered_set == my_set and my_set != my_ordered_set
# Remove circular references if isinstance(other, OrderedSet):
self.data.clear() return len(self) == len(other) and list(self) == list(other)
elif isinstance(other, set):
# Raise exception to avoid confusion.
raise TypeError(
'Cannot compare an `OrderedSet` to a `set` because '
'this comparison cannot be made symmetric: please '
'manually cast your `OrderedSet` into `set` before '
'performing this comparison.')
else:
return NotImplemented
# NB: Contrary to the other implementation above, we do not override
# the `__del__` method. On one hand, this is not needed since this
# implementation does not add circular references. Moreover, one should
# not clear the underlying dictionary holding the data as soon as the
# ordered set is cleared from memory, because there may still be
# pointers to this dictionary.
if __name__ == '__main__': if __name__ == '__main__':
print(OrderedSet('abracadaba')) print list(OrderedSet('abracadaba'))
print(OrderedSet('simsalabim')) print list(OrderedSet('simsalabim'))
print OrderedSet('boom') == OrderedSet('moob')
print OrderedSet('boom') == 'moob'
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论