[Python-Dev] Retrieve an arbitrary element from asetwithoutremoving it (original) (raw)
Steven D'Aprano steve at pearwood.info
Mon Nov 9 21:16:56 CET 2009
- Previous message: [Python-Dev] Retrieve an arbitrary element from asetwithoutremoving it
- Next message: [Python-Dev] Retrieve an arbitrary element from asetwithoutremoving it
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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 getfirst() 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 ... dis.dis(first) 2 0 SETUP_LOOP 15 (to 18) 3 LOAD_GLOBAL 0 (iterator) 6 GET_ITER 7 FOR_ITER 7 (to 17) 10 STORE_FAST 0 (value)
3 13 LOAD_FAST 0 (value) 16 RETURN_VALUE >> 17 POP_BLOCK >> 18 LOAD_CONST 0 (None) 21 RETURN_VALUE
Is it possible for another thread to be called between the GET_ITER and STORE_FAST?
-- Steven D'Aprano
- Previous message: [Python-Dev] Retrieve an arbitrary element from asetwithoutremoving it
- Next message: [Python-Dev] Retrieve an arbitrary element from asetwithoutremoving it
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]