Re: [Python-Dev] Simpler finalization semantics (was Re: PEP 343 - Abstract Block Redux)

Guido writes: [a rather silly objection to Phillip's proposal that 'with x:' is a no-op when x lacks __enter__ and __exit__]
I know this is not a very strong argument, but my gut tells me this generalization of the with-statement is wrong, so I'll stick to it regardless of the strength of the argument. The real reason will come to me.
Perhaps the real reason is that it allows errors to pass silently. If I write with foo: BLOCK where I should have written with locked(foo): BLOCK ...it silently "succeeds" by doing nothing. I CLEARLY intended to do the appropriate cleanup (or locking, or whatever), but it doesn't happen. -- Michael Chermside

Michael Chermside wrote:
If I write
with foo: BLOCK
where I should have written
with locked(foo): BLOCK
...it silently "succeeds" by doing nothing. I CLEARLY intended to do the appropriate cleanup (or locking, or whatever), but it doesn't happen.
Ah, thanks. Like Guido, I had something in the back of my head saying it didn't like the idea, but I couldn't figure out the reason. I think you just nailed it. Plus, there is a nice alternative which is to provide a 'clean it up if it needs it' resource in the standard library: class resource(object): def __init__(self, obj): self.obj = obj self.enter = getattr(obj, "__enter__", None) self.exit = getattr(obj, "__exit__", None) def __enter__(self): if self.enter is not None: self.enter() # For consistency, always return the object return self.obj def __exit__(self, *exc_info): if self.exit is not None: self.exit(*exc_info) Then 'I don't know if this needs cleaning up or not' can be written: with resource(foo): # If foo needs cleaning up, it will be. A refinement would provide the option to specify the enter/exit methods directly: class resource(object): def __init__(self, obj, *other_args): self.obj = obj if other_args: if len(other_args) != 2: raise TypeError("need 1 or 3 arguments") self.enter = args[0] self.exit = None self.exit_no_args = args[1] else: self.enter = getattr(obj, "__enter__", None) self.exit = getattr(obj, "__exit__", None) self.exit_no_args = None def __enter__(self): if self.enter is not None: self.enter() # For consistency, always return the object return self.obj def __exit__(self, *exc_info): if self.exit is not None: self.exit(*exc_info) elif self.exit_no_args is not None: self.exit() That would let any object with a standard 'clean me up method' be easily used in a with statement: with resource(bar, None, bar.clear): # bar will be cleared when we're done Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com
participants (2)
-
Michael Chermside
-
Nick Coghlan