[Python-Dev] Retrieve an arbitrary element from a set without removing it

Steven D'Aprano steve at pearwood.info
Sat Oct 24 00:44:22 CEST 2009


On Sat, 24 Oct 2009 07:11:57 am John Arbash Meinel wrote:

> The point of my test was that it was a set with a *single* item, and
> 'break' was 30% faster than 'pass'. Which was surprising. 

Not really. See below.

> Certainly 
> the difference is huge if there are 10k items in the set.


Earlier you suggested that the difference may have been because of a 
potential "else" statement. That won't be it: if there's no "else" in 
the code, it's not compiled in:

>>> import dis
>>> dis.dis(compile("for x in s: break", "", "exec"))
  1           0 SETUP_LOOP              15 (to 18)
              3 LOAD_NAME                0 (s)
              6 GET_ITER
        >>    7 FOR_ITER                 7 (to 17)
             10 STORE_NAME               1 (x)
             13 BREAK_LOOP
             14 JUMP_ABSOLUTE            7
        >>   17 POP_BLOCK
        >>   18 LOAD_CONST               0 (None)
             21 RETURN_VALUE
>>>
>>> dis.dis(compile("for x in s: pass", "", "exec"))
  1           0 SETUP_LOOP              14 (to 17)
              3 LOAD_NAME                0 (s)
              6 GET_ITER
        >>    7 FOR_ITER                 6 (to 16)
             10 STORE_NAME               1 (x)
             13 JUMP_ABSOLUTE            7
        >>   16 POP_BLOCK
        >>   17 LOAD_CONST               0 (None)
             20 RETURN_VALUE



The difference is likely to be this:

for x in s: break

retrieves the first (only) element of the set, then immediately breaks 
out of the loop. This is very different from:

for x in s: pass

which retrieves the first element of the set, then tries to retrieve a 
second element, which fails and raises StopIteration, which is then 
caught, ending the loop. That's much more expensive.



-- 
Steven D'Aprano


More information about the Python-Dev mailing list