Created
February 16, 2011 16:13
-
-
Save ntamas/829638 to your computer and use it in GitHub Desktop.
complementerset object for Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class complementerset(object): | |
"""This object behaves more or less like a set, with one exception, | |
the membership checking. For a `complementerset` object, you can | |
define the elements which are *not* in the set, everything else is | |
contained in it. The semantics of the operators are the same as for | |
sets. | |
Usage example:: | |
>>> s = complementerset() | |
>>> "abc" in s | |
True | |
>>> s in s | |
True | |
>>> s -= set(["abc"]) | |
>>> s | |
complementerset(['abc']) | |
>>> "abc" in s | |
False | |
""" | |
__slots__ = ("_set", ) | |
def __init__(self, iterable=()): | |
"""Constructs a complementer set that contains everything except | |
the members of the given iterable.""" | |
self._set = set(iterable) | |
def difference_update(self, *args): | |
"""Removes all elements of another set from this set. | |
Example:: | |
>>> s = complementerset([1,2]) | |
>>> s.difference_update([4,5]) | |
>>> print s | |
complementerset([1, 2, 4, 5]) | |
>>> s.difference_update([2], [1,6], [7,5,"spam"]) | |
>>> print any(item in s for item in [2,1,6,7,5,"spam",4]) | |
False | |
""" | |
self._set.update(*args) | |
def discard(self, member): | |
"""Removes an element from the complementer set if it is a member. | |
Example:: | |
>>> s = complementerset() | |
>>> s.discard(2) | |
>>> print s | |
complementerset([2]) | |
>>> s.discard(2) | |
>>> print s | |
complementerset([2]) | |
""" | |
self._set.add(member) | |
def iterexcluded(self): | |
"""Iterates over the items excluded from the complementer set. | |
Example:: | |
>>> s = complementerset([5, 7, 4]) | |
>>> print sorted(list(s.iterexcluded())) | |
[4, 5, 7] | |
""" | |
return iter(self._set) | |
def remove(self, member): | |
"""Removes an element from the complementer set; it must be a member. | |
If the element is not a member, raises a ``KeyError``. | |
Example:: | |
>>> s = complementerset() | |
>>> s.remove(2) | |
>>> print s | |
complementerset([2]) | |
>>> s.remove(2) | |
Traceback (most recent call last): | |
File "<stdin>", line 4, in ? | |
KeyError: 2 | |
""" | |
if member in self._set: | |
raise KeyError(member) | |
self._set.add(member) | |
def __and__(self, other): | |
"""Example:: | |
>>> s = complementerset() | |
>>> s2 = set([1,2,3]) | |
>>> (s & s2) == s2 | |
True | |
>>> s = complementerset([3,4]) | |
>>> (s & s2) == set([1,2]) | |
True | |
>>> (s & complementerset([1,2,3])) == complementerset([1,2,3,4]) | |
True | |
""" | |
if isinstance(other, self.__class__): | |
return complementerset(self._set | other._set) | |
self._ensure_set(other) | |
return set(other) - self._set | |
def __contains__(self, what): | |
"""Example:: | |
>>> s = complementerset([1,2]) | |
>>> s in s | |
True | |
>>> "foo" in s | |
True | |
>>> 1 in s | |
False | |
""" | |
if hasattr(what, "__hash__"): | |
return what not in self._set | |
else: | |
return True | |
def __eq__(self, other): | |
"""Example:: | |
>>> s = complementerset([1,2]) | |
>>> s == complementerset([1,2]) | |
True | |
>>> s == complementerset([1,2,3]) | |
False | |
>>> s == 1 | |
False | |
""" | |
return isinstance(other, self.__class__) and \ | |
self._set == other._set | |
def __ge__(self, other): | |
"""Example:: | |
>>> s = complementerset() | |
>>> s2 = complementerset() | |
>>> s2 >= s | |
True | |
>>> s >= s2 | |
True | |
>>> s >= complementerset([1,2]) | |
True | |
>>> s >= set([1,2,3]) | |
True | |
>>> s >= 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
>>> complementerset([1,2,3]) >= complementerset([1,2,3]) | |
True | |
>>> complementerset([1,2]) >= complementerset([2,3,4]) | |
False | |
""" | |
if isinstance(other, self.__class__): | |
return self._set <= other._set | |
self._ensure_set(other) | |
return True | |
def __gt__(self, other): | |
"""Example:: | |
>>> s = complementerset() | |
>>> s2 = complementerset() | |
>>> s2 > s | |
False | |
>>> s > s2 | |
False | |
>>> s > complementerset([1,2]) | |
True | |
>>> s > set([1,2,3]) | |
True | |
>>> s > 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
>>> complementerset([1,2,3]) > complementerset([1,2,3]) | |
False | |
>>> complementerset([1,2]) > complementerset([1,2,3]) | |
True | |
>>> complementerset([1,2,3]) > complementerset([1,2]) | |
False | |
>>> complementerset([1,2]) > complementerset([2,3,4]) | |
False | |
""" | |
return self != other and self >= other | |
def __iand__(self, other): | |
"""Example:: | |
>>> s = complementerset([3,4,5]) | |
>>> s &= s | |
>>> s == complementerset([3, 4, 5]) | |
True | |
>>> s &= complementerset([5,6]) | |
>>> s | |
complementerset([3, 4, 5, 6]) | |
>>> s &= set([1,2,3]) | |
>>> s == set([1, 2]) | |
True | |
>>> s = complementerset() | |
>>> s &= 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
""" | |
if isinstance(other, self.__class__): | |
self._set |= other._set | |
return self | |
self._ensure_set(other) | |
return other - self._set | |
def __ior__(self, other): | |
"""Example:: | |
>>> s = complementerset([3,4,5]) | |
>>> s |= s | |
>>> s == complementerset([3, 4, 5]) | |
True | |
>>> s |= set([1,2,3]) | |
>>> s == complementerset([4, 5]) | |
True | |
>>> s |= complementerset([1, 4]) | |
>>> s | |
complementerset([4]) | |
>>> s |= 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
""" | |
if isinstance(other, self.__class__): | |
self._set &= other._set | |
return self | |
self._ensure_set(other) | |
self._set -= other | |
return self | |
def __isub__(self, other): | |
"""Example:: | |
>>> s = complementerset() | |
>>> s -= set([1,2,3]) | |
>>> s | |
complementerset([1, 2, 3]) | |
>>> s -= 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
>>> s -= complementerset([1,2,4]) | |
>>> s | |
set([4]) | |
""" | |
if isinstance(other, self.__class__): | |
return other._set - self._set | |
self._ensure_set(other) | |
self._set |= other | |
return self | |
def __le__(self, other): | |
"""Example:: | |
>>> s = complementerset() | |
>>> s2 = complementerset() | |
>>> s2 <= s | |
True | |
>>> s <= s2 | |
True | |
>>> s <= complementerset([1,2]) | |
False | |
>>> s <= set([1,2,3]) | |
False | |
>>> s <= 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
>>> complementerset([1,2,3]) <= complementerset([1,2,3]) | |
True | |
>>> complementerset([1,2]) <= complementerset([2,3,4]) | |
False | |
""" | |
if isinstance(other, self.__class__): | |
return self._set >= other._set | |
self._ensure_set(other) | |
return False | |
def __lt__(self, other): | |
"""Example:: | |
>>> s = complementerset() | |
>>> s2 = complementerset() | |
>>> s2 < s | |
False | |
>>> s < s2 | |
False | |
>>> s < complementerset([1,2]) | |
False | |
>>> complementerset([1,2]) < s | |
True | |
>>> s < set([1,2,3]) | |
False | |
>>> s < 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
>>> complementerset([1,2,3]) < complementerset([1,2,3]) | |
False | |
>>> complementerset([1,2]) < complementerset([1,2,3]) | |
False | |
>>> complementerset([1,2,3]) < complementerset([1,2]) | |
True | |
>>> complementerset([1,2]) < complementerset([2,3,4]) | |
False | |
""" | |
return self != other and self <= other | |
def __ne__(self, other): | |
return not self == other | |
def __or__(self, other): | |
"""Example:: | |
>>> s = complementerset([2,4,5]) | |
>>> s | set([1,2,3]) == complementerset([4, 5]) | |
True | |
>>> s | complementerset([1,2]) | |
complementerset([2]) | |
>>> s | 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
""" | |
if isinstance(other, self.__class__): | |
return complementerset(self._set & other._set) | |
self._ensure_set(other) | |
return complementerset(self._set - other) | |
def __rand__(self, other): | |
"""Example:: | |
>>> s = complementerset([2,4,5]) | |
>>> set([1,2,3]) & s == set([1,3]) | |
True | |
>>> complementerset([1,2,3]) & s == complementerset([1,2,3,4,5]) | |
True | |
>>> 2 & s | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
""" | |
return self & other | |
def __ror__(self, other): | |
"""Example:: | |
>>> s = complementerset([2,4,5]) | |
>>> set([1,2,3]) | s == complementerset([4, 5]) | |
True | |
>>> complementerset([1, 2]) | s | |
complementerset([2]) | |
>>> 2 | s | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
""" | |
return self | other | |
def __repr__(self): | |
return "%s(%r)" % (self.__class__.__name__, list(self._set)) | |
def __rsub__(self, other): | |
"""Example:: | |
>>> set([1,2,3]) - complementerset() | |
set([]) | |
>>> (set([1,2,3]) - complementerset([1,2,4])) == set([1,2]) | |
True | |
>>> 2 - complementerset() | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
""" | |
if isinstance(other, self.__class__): | |
raise NotImplementedError | |
self._ensure_set(other) | |
return other.intersection(self._set) | |
def __sub__(self, other): | |
"""Example:: | |
>>> complementerset() - set([1,2,3]) | |
complementerset([1, 2, 3]) | |
>>> complementerset([1,2,3]) - complementerset([2,4]) | |
set([4]) | |
>>> complementerset([3,4]) - set([1,2,3]) | |
complementerset([1, 2, 3, 4]) | |
>>> complementerset() - 2 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
NotImplementedError | |
""" | |
if isinstance(other, self.__class__): | |
return other._set - self._set | |
self._ensure_set(other) | |
return complementerset(self._set | other) | |
@staticmethod | |
def _ensure_set(obj): | |
if not isinstance(obj, (set, frozenset, complementerset)): | |
raise NotImplementedError |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment