On Dec 14, 12:01 am, Steven D'Aprano <steve +comp.lang.pyt...@pearwood.info> wrote: > [...] > > So the normal lookup rules that apply to data attributes, namely > instance, then class, then superclasses, also applies to methods in > Python. In languages that don't allow that sort of thing, like Java, you > need to use convoluted design patterns like Dynamic Proxy to make it > work. In Python, you just create a method and attach it on the instance. > > http://stackoverflow.com/questions/8260740/override-a-method-for-an- > instance-of-a-class > > But this doesn't apply for special dunder attributes like __exit__, for > speed reasons. (For new-style classes only, classic classes have no such > special casing. This makes automatic delegation a breeze in Python 2 with > classic classes, and a PITA in Python 3. Boo hiss.)
Thanks to all who responded. Basically, I think the special casing of the "dunder" attributes threw me off. Typically, I would just build context managers from a class, but I wanted to experiment with instances that were built up without the standard Python class mechanisms, instead following a Javascript-like closure-based object creation model. This is what I came up with: class WithWrapper: def __init__(self, obj): self.obj = obj def __enter__(self): self.obj['enter']() def __exit__(self, *args): self.obj['exit'](*args) def greeter_context(hello, goodbye): return { 'enter': lambda: print("---\n" + hello), 'exit': lambda *args: print(goodbye) } gc_french = greeter_context("salut", "a plus tard") with WithWrapper(gc_french): print("doing stuff") gc_slang = greeter_context("yo", "later") with WithWrapper(gc_slang): print("doing stuff") -- http://mail.python.org/mailman/listinfo/python-list