Try, except...retry?
Robert Brewer
fumanchu at amor.org
Fri Nov 14 01:58:29 EST 2003
Alex Martelli wrote:
> In retrospect, it WOULD perhaps be better if setdefault was designed
> to take a callable (and optional args for it) and only call it if and
> when needed -- that would add a little speed and clarity
>
> Yes, flags (hiding control flow in data!) and repeated code
> do suck, but
> you need neither to get exactly the same semantics as your
> desideratum:
>
> while True:
> try: allPiranhas['Doug'].weapon = u'satire'
> except KeyError: allPiranhas['Doug'] = Pirhana()
> else: break
>
> I could be wrong, of course: there is nothing that appears to me
> to be "outrageously nonPythonic" in your proposal -- it just seems
> that new statements need to be more of a win than this in order to
> stand a chance. But a PEP on this is surely warranted, if you want
> to try one.
>
> No special "implications", as the semantics are just about the
> same as the above-indicated (flags-less, duplication-less)
> "while True:" loop that is so easy to code explicitly today.
>
> It's just that, partly because of this (and attendant benefits
> that writing out "while" DOES clearly indicate to the reader
> that the following code may repeat, etc etc), it does not seem
> to me that 'retry' is worth adding. But unless somebody does
> write a PEP, you'll just have my opinion about this...
Agreed. I'm new enough I'm still easy to convince. :) On a lark, I
decided to dump the bytecodes and see what I could see. It comes out, in
my math, to about 20 bytecodes saved using "retry" instead of "while
True", mostly due to saving the nested block. See the lines I've marked
with a * below, which I think would be taken out if we had retry. I'm
not a master of Python, I assume the left column in dis.dis() output
increments by more than one to mean that instruction takes more cycles.
I also assume byte 60 would have to be replaced with a JUMP_ABSOLUTE to
SETUP_EXCEPT. It depends on whether SETUP_EXCEPT would have to be
reexecuted again--does it? Anyone?
>>> def loop():
... while True:
... try:
... print a
... except:
... a = 0
... else:
... break
...
>>> loop()
0
>>> dis.dis(loop)
0 SET_LINENO 1
* 3 SET_LINENO 2
* 6 SETUP_LOOP 56 (to 65)
* >> 9 SET_LINENO 2
* 12 LOAD_GLOBAL 0 (True)
* 15 JUMP_IF_FALSE 45 (to 63)
* 18 POP_TOP
19 SET_LINENO 3
22 SETUP_EXCEPT 12 (to 37)
25 SET_LINENO 4
28 LOAD_FAST 0 (a)
31 PRINT_ITEM
32 PRINT_NEWLINE
33 POP_BLOCK
34 JUMP_FORWARD 19 (to 56)
>> 37 SET_LINENO 5
40 POP_TOP
41 POP_TOP
42 POP_TOP
43 SET_LINENO 6
46 LOAD_CONST 1 (0)
49 STORE_FAST 0 (a)
52 JUMP_FORWARD 5 (to 60)
55 END_FINALLY
* >> 56 SET_LINENO 8
* 59 BREAK_LOOP
* >> 60 JUMP_ABSOLUTE 9
>> 63 POP_TOP
64 POP_BLOCK
>> 65 LOAD_CONST 0 (None)
68 RETURN_VALUE
Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org
More information about the Python-list
mailing list