This snippet implements a pointed set, that is to say an ordinary set of elements with a distinguished element called the basepoint of the set. For example the seven days of the week could be stored in a pointed set, the basepoint being monday because today is monday. It is a very simple structure but use cases are easily found.

Edited 2 Years Ago by Gribouillis

#!/usr/bin/env python
# -*-coding: utf8-*-
# Author: Gribouillis for the python forum at
# Date: 2014 May 26
# License: Public Domain
# Use this code freely

from __future__ import (absolute_import, division,
                        print_function, unicode_literals)
from collections import MutableSet

__version__ = '0.0.2'

if repr(set([0])).startswith('{'): # python 3
    def _set_repr(aset):
        s = repr(aset)
        return 'set([{}])'.format(s[1:-1])
else: # python 2
    _set_repr = repr

class PointedSet(MutableSet):
    """PointedSet(iterable) --> new PointedSet instance.

    It is an error if @iterable is empty.
    This class implements a non empty ordinary set with a distinguished element
    called the basepoint. This element can be read and written through the attribute
    The selected element always belong to the set. Failing operations, such as
    attempts to empty the set or define an invalid basepoint may raise KeyError
    or TypeError.
    The class implements the MutableSet abstract interface defined in module
    The "pointed set" terminology is borrowed from mathematics. See for example

        >>> s = PointedSet(range(10))
        >>> s                               # doctest: +ELLIPSIS
        >>> len(s)
        >>> 0 <= s.basepoint < 10
        >>> s &= range(5)
        >>> s                               # doctest: +ELLIPSIS
        >>> sorted(s)
        [0, 1, 2, 3, 4]
        >>> s.basepoint = 3
        >>> s.basepoint
        >>> s.basepoint = 7
        Traceback (most recent call last):
        KeyError: 7
        >>> s.basepoint
        >>> s -= range(4)
        >>> s.basepoint
        >>> s
        >>> s.pop()
        Traceback (most recent call last):
        TypeError: discard would empty PointedSet

    __slots__ = ('_aggregate', '_basepoint')
    def __init__(self, iterable):
        self._aggregate = set(iterable)
            self._basepoint = next(iter(self._aggregate))
        except StopIteration:
            raise TypeError('PointedSet initialized from empty iterable')

    def basepoint(self):
        return self._basepoint
    def basepoint(self, item):
        if item in self._aggregate:
            self._basepoint = item
            raise KeyError(item)
    def __contains__(self, item):
        return item in self._aggregate
    def __iter__(self):
        return iter(self._aggregate)
    def __len__(self):
        return len(self._aggregate)
    def add(self, item):
    def discard(self, item):
        if item in self._aggregate:
            if len(self._aggregate) == 1:
                raise TypeError('discard would empty PointedSet')
                if self._basepoint not in self._aggregate:
                    self._basepoint = next(iter(self._aggregate))
    def __repr__(self):
        r = repr(self._aggregate)
        return "PointedS{}".format(_set_repr(self._aggregate)[1:])

if __name__ == "__main__":
    import doctest