提交 baac919b authored 作者: Olivier Delalleau's avatar Olivier Delalleau

A few improvements to OrderedSet implementation

* Can now construct an OrderedSet from a string * Potentially more efficient implementation of __iter__() in Python 2.4 * __eq__ behavior in the same in both implementations, and now forbids comparison to set to avoid confusing non-symmetric equality relations
上级 b412823a
...@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论