[Python-Dev] Retrieve an arbitrary element from asetwithoutremoving it
steve at pearwood.info
Mon Nov 9 21:16:56 CET 2009
On Tue, 10 Nov 2009 03:40:11 am Björn Lindqvist wrote:
> 2009/11/6 Raymond Hettinger <python at rcn.com>:
> > [me]
> >> Why not write a short, fast get_first() function for your utils
> >> directory and be done with it?
> >> That could work with sets, mappings, generators, and other
> >> containers and iterators.
> >> No need to fatten the set/frozenset API for something so trivial
> >> and so rarely needed.
> > Forgot to post the code. It is short, fast, and easy. It is
> > explicit about handing the case with an empty input. And it is
> > specific about which value it returns (always the first iterated
> > value; not an arbitrary one). There's no guessing about what it
> > does. It gets the job done.
> > def first(iterable):
> > 'Return the first value from a container or iterable. If empty,
> > raises LookupError'
> > for value in iterable:
> > return value
> > raise LookupError('no first value; iterable is empty')
> > If desired, it is not hard to change to the last time to return a
> > default value or some other exception.
> That function is very nice and genericly lisp-like. Couldn't that one
> be in the builtins? It would both solve the problem and avoid
> fattening the set API.
I'm not sure, but isn't that thread-unsafe?
Because sets aren't directly iterable, `for value in iterable` builds a
set_iterator operator. If another thread modifies the set after the
set_iterator is built, but before the value is looked up, you will get
a mysterious RuntimeError almost impossible to debug.
>>> def first(): # simplified
... for value in iterator:
... return value
2 0 SETUP_LOOP 15 (to 18)
3 LOAD_GLOBAL 0 (iterator)
7 FOR_ITER 7 (to 17)
10 STORE_FAST 0 (value)
3 13 LOAD_FAST 0 (value)
>> 17 POP_BLOCK
>> 18 LOAD_CONST 0 (None)
Is it possible for another thread to be called between the GET_ITER and
More information about the Python-Dev