From 5f3dd5eace44538b55c08df67c2e67a2705b9813 Mon Sep 17 00:00:00 2001 From: Mahmoud Hashemi Date: Wed, 1 Apr 2015 01:55:42 -0700 Subject: [PATCH] setutils docstrings --- boltons/setutils.py | 55 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/boltons/setutils.py b/boltons/setutils.py index 5950af2..d96d008 100644 --- a/boltons/setutils.py +++ b/boltons/setutils.py @@ -1,4 +1,15 @@ # -*- coding: utf-8 -*- +"""\ + +The :class:`set` type brings brings the practical expressiveness of +set theory to Python. It has a very rich API overall, but lacks a +couple of fundamental features. For one, sets are not ordered. On top +of this, sets are not indexable, i.e, my_set[8] will raise an +exception. The :class:`IndexedSet` type remedies both of these issues +without compromising on the excellent complexity characteristics of +Python's builtin set implementation. +""" + from bisect import bisect_left from itertools import chain, islice @@ -27,10 +38,10 @@ _COMPACTION_FACTOR = 8 class IndexedSet(MutableSet): """\ - IndexedSet maintains insertion order and uniqueness of inserted - elements. It's a hybrid type, mostly like an OrderedSet, but also - list-like, in that it supports indexing and slicing. - + IndexedSet is a :class:`collections.MutableSet` that maintains + insertion order and uniqueness of inserted elements. It's a hybrid + type, mostly like an OrderedSet, but also list-like, in that it + supports indexing and slicing: >>> x = IndexedSet(range(4) + range(8)) >>> x @@ -43,17 +54,26 @@ class IndexedSet(MutableSet): >>> ''.join(fcr[:fcr.index('.')]) 'frecditpo' - For the curious, the reason why IndexedSet does not support - __setitem__() (i.e, setting items based on index), and is not a - UniqueList, consider the following: + As you can see, the IndexedSet is almost like a UniqueList, + retaining only one copy of a given value, in the order it was + first added. For the curious, the reason why IndexedSet does not + support setting items based on index (i.e, ``__setitem__()``), + consider the following dilemma:: - my_indexed_set = [A, B, C, D] - my_indexed_set[2] = A + my_indexed_set = [A, B, C, D] + my_indexed_set[2] = A At this point, a set requires only one A, but a list would overwrite C. Overwriting C would change the length of the list, meaning that my_indexed_set[2] would not be A, as expected with a list, but rather D. So, no __setitem__(). + + Otherwise, the API strives to be as complete a union of the + :class:`list` and :class:`set` APIs as possible. + + Args: + other (iterable): An optional iterable used to initialize the set. + """ def __init__(self, other=None): self.item_index_map = dict() @@ -163,11 +183,13 @@ class IndexedSet(MutableSet): # set operations def add(self, item): + "set.add(item) -> add item to the set" if item not in self.item_index_map: self.item_index_map[item] = len(self.item_list) self.item_list.append(item) def remove(self, item): + "set.remove(item) -> remove item from the set, raises if not present" try: didx = self.item_index_map.pop(item) except KeyError: @@ -177,12 +199,14 @@ class IndexedSet(MutableSet): self._cull() def discard(self, item): + "set.discard(item) -> discard item from the set (does not raise)" try: self.remove(item) except KeyError: pass def clear(self): + "set.clear() -> empty the set" del self.item_list[:] del self.dead_indices[:] self.item_index_map.clear() @@ -255,6 +279,7 @@ class IndexedSet(MutableSet): # in-place set operations def update(self, *others): + "set.update() -> add values from one or more iterables" if not others: return # raise? elif len(others) == 1: @@ -329,6 +354,7 @@ class IndexedSet(MutableSet): return ret def pop(self, index=None): + "list.pop(index) -> remove the item at a given index (-1 by default)" item_index_map = self.item_index_map len_self = len(item_index_map) if index is None or index == -1 or index == len_self - 1: @@ -343,12 +369,14 @@ class IndexedSet(MutableSet): self._cull() return ret - def count(self, x): - if x in self.item_index_map: + def count(self, val): + "list.count(val) -> count number of instances of value (0 or 1)" + if val in self.item_index_map: return 1 return 0 def reverse(self): + "list.reverse() -> reverse the contents of the set in-place" reversed_list = list(reversed(self)) self.item_list[:] = reversed_list for i, item in enumerate(self.item_list): @@ -356,6 +384,7 @@ class IndexedSet(MutableSet): del self.dead_indices[:] def sort(self): + "list.sort() -> sort the contents of the set in-place" sorted_list = sorted(self) if sorted_list == self.item_list: return @@ -365,10 +394,12 @@ class IndexedSet(MutableSet): del self.dead_indices[:] def index(self, val): + "list.index(val) -> get the index of a value, raises if not present" try: return self.item_index_map[val] except KeyError: - raise ValueError('%r is not in IndexedSet' % val) + cn = self.__class__.__name__ + raise ValueError('%r is not in %s' % (val, cn)) # Tests of a manner