[Python-Dev] Retrieve an arbitrary element from a setwithoutremoving it (original) (raw)

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 IMHO).

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):
        break
else:
    x = default_x    # or perhaps raise in cases where there
                     # theoretically should be an element

My reasoning for the given behaviour is as follows:

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