On the 'using old semantics when you really want to' part, that's very well possible with a decorator under the proposed semantics: def caching(**cachevars): def inner(func): def wrapper(**argdict): for var in cachevars: if not var in argdict: argdict[var] = cachevars[var] return func(**argdict) return wrapper return inner @caching(cache={}) def foo(in, cache): result = bar(in) cache[in] = result return result This implementation of caching doesn't handle positional args, but it can be made to. One such decorator would still be a net win of several hundred lines of code in the standard lib. Of course, IMHO, the real fix to this is to 1) have default expressions be evaluated at calltime, and 2) have _all_ lexical variables be bound at definition time and 3) make them immutable. Then something like lst = [] for i in range(10): lst.append(lambda i: i*i) would work. That would be a real win for functional programming. (good thing) Unfortunately Guido's decided not to support (1), and (2) has been proposed some time ago and didn't make it. In both cases because it would be to big a departure from how Python currently works. (3) is quite impossible in a language like python. <mode=dreaming> I just hope if python were designed today it would have done these. </mode> - Jan