ยปCore Development>Code coverage>Lib/sets.py

Python code coverage for Lib/sets.py

#countcontent
1n/a"""Classes to represent arbitrary sets (including sets of sets).
2n/a
3n/aThis module implements sets using dictionaries whose values are
4n/aignored. The usual operations (union, intersection, deletion, etc.)
5n/aare provided as both methods and operators.
6n/a
7n/aImportant: sets are not sequences! While they support 'x in s',
8n/a'len(s)', and 'for x in s', none of those operations are unique for
9n/asequences; for example, mappings support all three as well. The
10n/acharacteristic operation for sequences is subscripting with small
11n/aintegers: s[i], for i in range(len(s)). Sets don't support
12n/asubscripting at all. Also, sequences allow multiple occurrences and
13n/atheir elements have a definite order; sets on the other hand don't
14n/arecord multiple occurrences and don't remember the order of element
15n/ainsertion (which is why they don't support s[i]).
16n/a
17n/aThe following classes are provided:
18n/a
19n/aBaseSet -- All the operations common to both mutable and immutable
20n/a sets. This is an abstract class, not meant to be directly
21n/a instantiated.
22n/a
23n/aSet -- Mutable sets, subclass of BaseSet; not hashable.
24n/a
25n/aImmutableSet -- Immutable sets, subclass of BaseSet; hashable.
26n/a An iterable argument is mandatory to create an ImmutableSet.
27n/a
28n/a_TemporarilyImmutableSet -- A wrapper around a Set, hashable,
29n/a giving the same hash value as the immutable set equivalent
30n/a would have. Do not use this class directly.
31n/a
32n/aOnly hashable objects can be added to a Set. In particular, you cannot
33n/areally add a Set as an element to another Set; if you try, what is
34n/aactually added is an ImmutableSet built from it (it compares equal to
35n/athe one you tried adding).
36n/a
37n/aWhen you ask if `x in y' where x is a Set and y is a Set or
38n/aImmutableSet, x is wrapped into a _TemporarilyImmutableSet z, and
39n/awhat's tested is actually `z in y'.
40n/a
411"""
42n/a
43n/a# Code history:
44n/a#
45n/a# - Greg V. Wilson wrote the first version, using a different approach
46n/a# to the mutable/immutable problem, and inheriting from dict.
47n/a#
48n/a# - Alex Martelli modified Greg's version to implement the current
49n/a# Set/ImmutableSet approach, and make the data an attribute.
50n/a#
51n/a# - Guido van Rossum rewrote much of the code, made some API changes,
52n/a# and cleaned up the docstrings.
53n/a#
54n/a# - Raymond Hettinger added a number of speedups and other
55n/a# improvements.
56n/a
571from itertools import ifilter, ifilterfalse
58n/a
591__all__ = ['BaseSet', 'Set', 'ImmutableSet']
60n/a
611import warnings
621warnings.warn("the sets module is deprecated", DeprecationWarning,
631 stacklevel=2)
64n/a
652class BaseSet(object):
661 """Common base class for mutable and immutable sets."""
67n/a
681 __slots__ = ['_data']
69n/a
70n/a # Constructor
71n/a
721 def __init__(self):
73n/a """This is an abstract class."""
74n/a # Don't call this from a concrete subclass!
750 if self.__class__ is BaseSet:
760 raise TypeError, ("BaseSet is an abstract class. "
77n/a "Use Set or ImmutableSet.")
78n/a
79n/a # Standard protocols: __len__, __repr__, __str__, __iter__
80n/a
811 def __len__(self):
82n/a """Return the number of elements of a set."""
83314 return len(self._data)
84n/a
851 def __repr__(self):
86n/a """Return string representation of a set.
87n/a
88n/a This looks like 'Set([<list of elements>])'.
89n/a """
9016 return self._repr()
91n/a
92n/a # __str__ is the same as __repr__
931 __str__ = __repr__
94n/a
951 def _repr(self, sorted=False):
9616 elements = self._data.keys()
9716 if sorted:
985 elements.sort()
9916 return '%s(%r)' % (self.__class__.__name__, elements)
100n/a
1011 def __iter__(self):
102n/a """Return an iterator over the elements or a set.
103n/a
104n/a This is the keys iterator for the underlying dict.
105n/a """
106208 return self._data.iterkeys()
107n/a
108n/a # Three-way comparison is not supported. However, because __eq__ is
109n/a # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and
110n/a # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this
111n/a # case).
112n/a
1131 def __cmp__(self, other):
1141 raise TypeError, "can't compare sets using cmp()"
115n/a
116n/a # Equality comparisons using the underlying dicts. Mixed-type comparisons
117n/a # are allowed here, where Set == z for non-Set z always returns False,
118n/a # and Set != z always True. This allows expressions like "x in y" to
119n/a # give the expected result when y is a sequence of mixed types, not
120n/a # raising a pointless TypeError just because y contains a Set, or x is
121n/a # a Set and y contain's a non-set ("in" invokes only __eq__).
122n/a # Subtle: it would be nicer if __eq__ and __ne__ could return
123n/a # NotImplemented instead of True or False. Then the other comparand
124n/a # would get a chance to determine the result, and if the other comparand
125n/a # also returned NotImplemented then it would fall back to object address
126n/a # comparison (which would always return False for __eq__ and always
127n/a # True for __ne__). However, that doesn't work, because this type
128n/a # *also* implements __cmp__: if, e.g., __eq__ returns NotImplemented,
129n/a # Python tries __cmp__ next, and the __cmp__ here then raises TypeError.
130n/a
1311 def __eq__(self, other):
132146 if isinstance(other, BaseSet):
133130 return self._data == other._data
134n/a else:
13516 return False
136n/a
1371 def __ne__(self, other):
13826 if isinstance(other, BaseSet):
13912 return self._data != other._data
140n/a else:
14114 return True
142n/a
143n/a # Copying operations
144n/a
1451 def copy(self):
146n/a """Return a shallow copy of a set."""
14711 result = self.__class__()
14811 result._data.update(self._data)
14911 return result
150n/a
1511 __copy__ = copy # For the copy module
152n/a
1531 def __deepcopy__(self, memo):
154n/a """Return a deep copy of a set; used by copy module."""
155n/a # This pre-creates the result and inserts it in the memo
156n/a # early, in case the deep copy recurses into another reference
157n/a # to this same set. A set can't be an element of itself, but
158n/a # it can certainly contain an object that has a reference to
159n/a # itself.
1605 from copy import deepcopy
1615 result = self.__class__()
1625 memo[id(self)] = result
1635 data = result._data
1645 value = True
16511 for elt in self:
1666 data[deepcopy(elt, memo)] = value
1675 return result
168n/a
169n/a # Standard set operations: union, intersection, both differences.
170n/a # Each has an operator version (e.g. __or__, invoked with |) and a
171n/a # method version (e.g. union).
172n/a # Subtle: Each pair requires distinct code so that the outcome is
173n/a # correct when the type of other isn't suitable. For example, if
174n/a # we did "union = __or__" instead, then Set().union(3) would return
175n/a # NotImplemented instead of raising TypeError (albeit that *why* it
176n/a # raises TypeError as-is is also a bit subtle).
177n/a
1781 def __or__(self, other):
179n/a """Return the union of two sets as a new set.
180n/a
181n/a (I.e. all elements that are in either set.)
182n/a """
18345 if not isinstance(other, BaseSet):
1847 return NotImplemented
18538 return self.union(other)
186n/a
1871 def union(self, other):
188n/a """Return the union of two sets as a new set.
189n/a
190n/a (I.e. all elements that are in either set.)
191n/a """
19245 result = self.__class__(self)
19345 result._update(other)
19443 return result
195n/a
1961 def __and__(self, other):
197n/a """Return the intersection of two sets as a new set.
198n/a
199n/a (I.e. all elements that are in both sets.)
200n/a """
20147 if not isinstance(other, BaseSet):
2027 return NotImplemented
20340 return self.intersection(other)
204n/a
2051 def intersection(self, other):
206n/a """Return the intersection of two sets as a new set.
207n/a
208n/a (I.e. all elements that are in both sets.)
209n/a """
21054 if not isinstance(other, BaseSet):
21114 other = Set(other)
21250 if len(self) <= len(other):
21332 little, big = self, other
214n/a else:
21518 little, big = other, self
21650 common = ifilter(big._data.__contains__, little)
21750 return self.__class__(common)
218n/a
2191 def __xor__(self, other):
220n/a """Return the symmetric difference of two sets as a new set.
221n/a
222n/a (I.e. all elements that are in exactly one of the sets.)
223n/a """
22424 if not isinstance(other, BaseSet):
2257 return NotImplemented
22617 return self.symmetric_difference(other)
227n/a
2281 def symmetric_difference(self, other):
229n/a """Return the symmetric difference of two sets as a new set.
230n/a
231n/a (I.e. all elements that are in exactly one of the sets.)
232n/a """
23324 result = self.__class__()
23424 data = result._data
23524 value = True
23624 selfdata = self._data
23724 try:
23824 otherdata = other._data
2397 except AttributeError:
2407 otherdata = Set(other)._data
241240 for elt in ifilterfalse(otherdata.__contains__, selfdata):
242218 data[elt] = value
243238 for elt in ifilterfalse(selfdata.__contains__, otherdata):
244216 data[elt] = value
24522 return result
246n/a
2471 def __sub__(self, other):
248n/a """Return the difference of two sets as a new Set.
249n/a
250n/a (I.e. all elements that are in this set and not in the other.)
251n/a """
25242 if not isinstance(other, BaseSet):
2537 return NotImplemented
25435 return self.difference(other)
255n/a
2561 def difference(self, other):
257n/a """Return the difference of two sets as a new Set.
258n/a
259n/a (I.e. all elements that are in this set and not in the other.)
260n/a """
26152 result = self.__class__()
26252 data = result._data
26352 try:
26452 otherdata = other._data
2657 except AttributeError:
2667 otherdata = Set(other)._data
26750 value = True
268570 for elt in ifilterfalse(otherdata.__contains__, self):
269520 data[elt] = value
27050 return result
271n/a
272n/a # Membership test
273n/a
2741 def __contains__(self, element):
275n/a """Report whether an element is a member of a set.
276n/a
277n/a (Called in response to the expression `element in self'.)
278n/a """
2794 try:
2804 return element in self._data
2810 except TypeError:
2820 transform = getattr(element, "__as_temporarily_immutable__", None)
2830 if transform is None:
2840 raise # re-raise the TypeError exception we caught
2850 return transform() in self._data
286n/a
287n/a # Subset and superset test
288n/a
2891 def issubset(self, other):
290n/a """Report whether another set contains this set."""
29142 self._binary_sanity_check(other)
29228 if len(self) > len(other): # Fast check for obvious cases
2934 return False
29424 for elt in ifilterfalse(other._data.__contains__, self):
2954 return False
29620 return True
297n/a
2981 def issuperset(self, other):
299n/a """Report whether this set contains another set."""
30041 self._binary_sanity_check(other)
30127 if len(self) < len(other): # Fast check for obvious cases
3024 return False
30323 for elt in ifilterfalse(self._data.__contains__, other):
3045 return False
30518 return True
306n/a
307n/a # Inequality comparisons using the is-subset relation.
3081 __le__ = issubset
3091 __ge__ = issuperset
310n/a
3111 def __lt__(self, other):
31225 self._binary_sanity_check(other)
31310 return len(self) < len(other) and self.issubset(other)
314n/a
3151 def __gt__(self, other):
31625 self._binary_sanity_check(other)
31710 return len(self) > len(other) and self.issuperset(other)
318n/a
319n/a # We inherit object.__hash__, so we must deny this explicitly
3201 __hash__ = None
321n/a
322n/a # Assorted helpers
323n/a
3241 def _binary_sanity_check(self, other):
325n/a # Check that the other argument to a binary operation is also
326n/a # a set, raising a TypeError otherwise.
327182 if not isinstance(other, BaseSet):
32886 raise TypeError, "Binary operation only permitted between sets"
329n/a
3301 def _compute_hash(self):
331n/a # Calculate hash code for a set by xor'ing the hash codes of
332n/a # the elements. This ensures that the hash code does not depend
333n/a # on the order in which elements are added to the set. This is
334n/a # not called __hash__ because a BaseSet should not be hashable;
335n/a # only an ImmutableSet is hashable.
33620 result = 0
33756 for elt in self:
33836 result ^= hash(elt)
33920 return result
340n/a
3411 def _update(self, iterable):
342n/a # The main loop for update() and the subclass __init__() methods.
343634 data = self._data
344n/a
345n/a # Use the fast update() method when a dictionary is available.
346634 if isinstance(iterable, BaseSet):
34795 data.update(iterable._data)
34895 return
349n/a
350539 value = True
351n/a
352539 if type(iterable) in (list, tuple, xrange):
353n/a # Optimized: we know that __iter__() and next() can't
354n/a # raise TypeError, so we can move 'try:' out of the loop.
355409 it = iter(iterable)
356418 while True:
357418 try:
3581886 for element in it:
3591477 data[element] = value
360409 return
3619 except TypeError:
3629 transform = getattr(element, "__as_immutable__", None)
3639 if transform is None:
3640 raise # re-raise the TypeError exception we caught
3659 data[transform()] = value
366n/a else:
367n/a # Safe: only catch TypeError where intended
368546 for element in iterable:
369416 try:
370416 data[element] = value
3710 except TypeError:
3720 transform = getattr(element, "__as_immutable__", None)
3730 if transform is None:
3740 raise # re-raise the TypeError exception we caught
3750 data[transform()] = value
376n/a
377n/a
3782class ImmutableSet(BaseSet):
3791 """Immutable set class."""
380n/a
3811 __slots__ = ['_hashcode']
382n/a
383n/a # BaseSet + hashing
384n/a
3851 def __init__(self, iterable=None):
386n/a """Construct an immutable set from an optional iterable."""
38724 self._hashcode = None
38824 self._data = {}
38924 if iterable is not None:
39024 self._update(iterable)
391n/a
3921 def __hash__(self):
39332 if self._hashcode is None:
39418 self._hashcode = self._compute_hash()
39532 return self._hashcode
396n/a
3971 def __getstate__(self):
3980 return self._data, self._hashcode
399n/a
4001 def __setstate__(self, state):
4010 self._data, self._hashcode = state
402n/a
4032class Set(BaseSet):
4041 """ Mutable set class."""
405n/a
4061 __slots__ = []
407n/a
408n/a # BaseSet + operations requiring mutability; no hashing
409n/a
4101 def __init__(self, iterable=None):
411n/a """Construct a set from an optional iterable."""
412655 self._data = {}
413655 if iterable is not None:
414553 self._update(iterable)
415n/a
4161 def __getstate__(self):
417n/a # getstate's results are ignored if it is not
4184 return self._data,
419n/a
4201 def __setstate__(self, data):
4214 self._data, = data
422n/a
423n/a # In-place union, intersection, differences.
424n/a # Subtle: The xyz_update() functions deliberately return None,
425n/a # as do all mutating operations on built-in container types.
426n/a # The __xyz__ spellings have to return self, though.
427n/a
4281 def __ior__(self, other):
429n/a """Update a set with the union of itself and another."""
43012 self._binary_sanity_check(other)
4315 self._data.update(other._data)
4325 return self
433n/a
4341 def union_update(self, other):
435n/a """Update a set with the union of itself and another."""
43612 self._update(other)
437n/a
4381 def __iand__(self, other):
439n/a """Update a set with the intersection of itself and another."""
44013 self._binary_sanity_check(other)
4416 self._data = (self & other)._data
4426 return self
443n/a
4441 def intersection_update(self, other):
445n/a """Update a set with the intersection of itself and another."""
4468 if isinstance(other, BaseSet):
4471 self &= other
448n/a else:
4497 self._data = (self.intersection(other))._data
450n/a
4511 def __ixor__(self, other):
452n/a """Update a set with the symmetric difference of itself and another."""
45312 self._binary_sanity_check(other)
4545 self.symmetric_difference_update(other)
4555 return self
456n/a
4571 def symmetric_difference_update(self, other):
458n/a """Update a set with the symmetric difference of itself and another."""
45913 data = self._data
46013 value = True
46113 if not isinstance(other, BaseSet):
4627 other = Set(other)
46311 if self is other:
4641 self.clear()
46539 for elt in other:
46628 if elt in data:
46711 del data[elt]
468n/a else:
46917 data[elt] = value
470n/a
4711 def __isub__(self, other):
472n/a """Remove all elements of another set from this set."""
47312 self._binary_sanity_check(other)
4745 self.difference_update(other)
4755 return self
476n/a
4771 def difference_update(self, other):
478n/a """Remove all elements of another set from this set."""
47913 data = self._data
48013 if not isinstance(other, BaseSet):
4817 other = Set(other)
48211 if self is other:
4831 self.clear()
48422 for elt in ifilter(data.__contains__, other):
48511 del data[elt]
486n/a
487n/a # Python dict-like mass mutations: update, clear
488n/a
4891 def update(self, iterable):
490n/a """Add all values from an iterable (such as a list or file)."""
4910 self._update(iterable)
492n/a
4931 def clear(self):
494n/a """Remove all elements from this set."""
4953 self._data.clear()
496n/a
497n/a # Single-element mutations: add, remove, discard
498n/a
4991 def add(self, element):
500n/a """Add an element to a set.
501n/a
502n/a This has no effect if the element is already present.
503n/a """
5047 try:
5057 self._data[element] = True
5061 except TypeError:
5071 transform = getattr(element, "__as_immutable__", None)
5081 if transform is None:
5090 raise # re-raise the TypeError exception we caught
5101 self._data[transform()] = True
511n/a
5121 def remove(self, element):
513n/a """Remove an element from a set; it must be a member.
514n/a
515n/a If the element is not a member, raise a KeyError.
516n/a """
51713 try:
51813 del self._data[element]
5195 except TypeError:
5202 transform = getattr(element, "__as_temporarily_immutable__", None)
5212 if transform is None:
5220 raise # re-raise the TypeError exception we caught
5232 del self._data[transform()]
524n/a
5251 def discard(self, element):
526n/a """Remove an element from a set if it is a member.
527n/a
528n/a If the element is not a member, do nothing.
529n/a """
5307 try:
5317 self.remove(element)
5323 except KeyError:
5333 pass
534n/a
5351 def pop(self):
536n/a """Remove and return an arbitrary set element."""
5374 return self._data.popitem()[0]
538n/a
5391 def __as_immutable__(self):
540n/a # Return a copy of self as an immutable set
54110 return ImmutableSet(self)
542n/a
5431 def __as_temporarily_immutable__(self):
544n/a # Return self wrapped in a temporarily immutable set
5452 return _TemporarilyImmutableSet(self)
546n/a
547n/a
5482class _TemporarilyImmutableSet(BaseSet):
549n/a # Wrap a mutable set as if it was temporarily immutable.
550n/a # This only supplies hashing and equality comparisons.
551n/a
5521 def __init__(self, set):
5532 self._set = set
5542 self._data = set._data # Needed by ImmutableSet.__eq__()
555n/a
5561 def __hash__(self):
5572 return self._set._compute_hash()