Help me dig my way out of nested scoping

Terry Reedy tjreedy at udel.edu
Sun Apr 3 19:09:32 EDT 2005


"Brendan" <spam4bsimons at yahoo.ca> wrote in message 
news:1112562768.181026.180140 at l41g2000cwc.googlegroups.com...
> I have a function, call it F(x), which asks for two
> other functions as arguments, say A(x) and B(x).  ...

If I understand this and the rest, a third party library whose code you 
cannot modify (easily) has a function F with (at least) three parameters: 
A, B, and x.  During its operation, F calls A(x) and B(x).  Because of code 
commonality for the particular A and B arg funcs you want to feed to F, you 
want avoid duplication by having the first call to either to calculate both 
return values.

If F calls each of A and B exactly once and always in the same order and 
only for the value x you supply, the solution is pretty easy.  A calls AB, 
stashes the B value away where it can be retrieved, and return the A value. 
B retrieves the B value and returns it.  But your problem is the stash and 
retrieve part.  Solutions:
1. global variable (easiest)  - use global declaration in A;
2. closure variable - use mutable such as 1 element list (see below);
3. instance attribute - with A and B as methods.

2 is what you tried to do, but without knowing the mutable (list or dict) 
trick:

def ABwrapper():
  bsave = [None]
  def A(x):
    aval,bval = AB(x)
    bsave[0] = bval
    return aval
  def B(x):
    return bsave[0]
  return A,B

This works because A does not try to *rebind* bsave to a new object.  It 
only mutates the existing object.

If the order of calling changes, you need more logic.  If F calls A and B 
on multiple 'x's, as with, for instance, a derivative approximizer, then I 
would memoize A and/or B using the recipe posted here more than once and on 
the cookbook site and included in the new Python Cookbook v2 (and maybe v1, 
don't have it).

Terry J. Reedy






More information about the Python-list mailing list