[Python-Dev] Retrieve an arbitrary element from a setwithoutremoving it

Stephen J. Turnbull stephen at xemacs.org
Sat Oct 31 03:42:46 CET 2009

Steven D'Aprano writes:

 > The usual technique people tend to come up with is:
 > x = s.pop()
 > s.add(x)
 > Which strikes many people (including myself) as inelegant. Surely "get 
 > an element" is a more fundamental operation than "get an element and 
 > remove it"?

Not in a literal urn or bag.  See "sampling with replacement" in any
statistics text.  Note that in order to "have your cake and eat it
too" there's an implicit copy operation (although in Python it will be
a cheap ref copy rather than an expensive object copy).

I'm afraid that the various conflicting intuitions here are all
correct.  That is going to make design impossible without some
compelling use cases.

 > > What's wrong with using next()?  That is what it's for.
 > You can't call next() on a set. You have to call next(iter(set)).
 > [...]
 > Unless I missed something, this is so unobvious that nobody has
 > suggested it in the thread yet.

I've seen it at least twice (Nick suggested it IIRC), although that
may have been on Python-Ideas (which is where this thread belongs

 > If folks prefer a different name, by all means suggest it. I like
 > the name suggested by Wikipedia, "pick".

"Pick" has a connotation of removal in many contexts: "Pick a card,
any card".  "Pick it up off the floor" (it's not in the set of things
on the floor any more).  Like get, to me it has a flavor of "according
to some criterion": "a band of picked men".  I would expect a pick or
get operation to take an optional predicate.  But then TOOWTDI is

    for x in container:
        if predicate(x):
        x = default_x    # or perhaps raise in cases where there
                         # theoretically should be an element

 > My reasoning for the given behaviour is as follows:
 > * If you want the same element twice from a set,

Nobody is asking for that AFAICS.  The use case I have so far observed
people to have in mind is a cast from an equivalence class to a
representative member.  They don't care whether the member is the same
or not.  If they wanted iterator behavior, getting it would not be a
problem.  next(iter(foo_set)) is TOOWTDI.  If they wanted cyclical
behavior, itertools.cycle.  If they wanted random behavior, make a
list and choose from it.

In one leading subcase, the equivalence class is a singleton.  In this
use case what people really want, I suspect, is behavior like Python
strings and characters: a singleton set should provide the same
operations as its unique element and vice versa.

 > So having get() return the same value each time is not useful or 
 > necessary.

Which is not the point.  The point is that having get return a
different value if possible is not useful or necessary in at least
some of the leading use cases.  OTOH, we don't know enough about
"weird" use cases where having a different value returned is important
to decide how that should be done, where "weird" means "outside of the
list of already Obvious Ways".

 > No. Since sets are unordered, there's no way to seek to a specific 
 > element.

I think people will realize that in fact *these* sets are ordered and
they will demand a seek function for various practical purposes.

 > > Sorry for so many questions, but I honestly think there are too many
 > > unresolved design issues.

I have to agree with Raymond.

More information about the Python-Dev mailing list