At 09:56 PM 7/6/2006 -0400, Kevin Jacobs <[EMAIL PROTECTED]> wrote: >Why not extend the interface to the locals builtin and add a __getitem__ >that returns a proxy to access locals defined in other lexical scopes via >__{get/set/del}attr_: > >def counter(num): > num = 1 > def inc(): > locals[1].num += 1 > return outer.num > return inc > > >Where, for CPython, locals[n] gives access to >NamespaceProxy(sys._getframe(n).f_locals).
That doesn't actually work, because sys._getframe(1) will give you inc()'s caller, *not* the frame where it was defined. > In addition to having a relatively pleasing and explicit syntax, this > may be a feasible method for allowing portable introspection into outer > scopes without having to export the whole frame object a la > sys._getframe(n). I strongly suspect that Jython, IronPython, and PyPy > would have little difficulty supporting (and optimizing) this construct. > >Lacking core language support, it is easy to roll an object that does just >what I suggest. Actual implementation is left to a more motivated reader, >of course. While I hesitate to describe anything as "impossible", I will note that an implementation with the syntax you suggest is not likely to be possible without resorting to ctypes or a C module, because the frame doesn't have a reference to the function, only the code object, and it's the function objects that own the closure cells. I think the only way you can reasonably accomplish rebinding in Python right now is to have a rebind(func, var=value) function, e.g.: def counter(num): def inc(): rebind(inc, num=num+1) return num return inc It doesn't allow augmented assignment, of course, and it also creates a circular reference between 'inc' and itself, requiring garbage collection to clean up. Anyway, the actual implementation of such a rebind function would basically be a bit of syntax sugar over this cookbook recipe: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440515 You'd want to just use the keyword argument names to figure out which cells of the function needed changing. And the whole thing would be really slow and complex. You'd probably be better off using function attributes: def counter(num): def inc(): inc.num+=1 return inc.num inc.num = num return inc It's not ideal, but *this* should probably be the pattern we recommend for rebinding, rather than "create a class" or "use an anonymous namespace argument". It can even be prettied up a little bit with a decorator to set the function attributes. def counter(num): @uses(num=num) def inc(): inc.num+=1 return inc.num return inc But that's about as good as it gets, which is nowhere near as good as: def counter(num): def inc(): nonlocal num num+=1 return num return inc On the other hand, the rebind() syntax actually is slightly cleaner in some respects: def counter(num): def inc(): rebind(num = num+1) return num return inc Maybe we should just make rebind() a fast builtin. ;) _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com