[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