Hi everyone
I'm new to Python, so forgive me if the solution to my question should
have been obvious. I have a function, call it F(x), which asks for two
other functions as arguments, say A(x) and B(x). A and B are most
efficiently evaluated at once, since they share much of the same math,
ie, A, B = AB(x), but F wants to call them independantly (it's part of
a third party library, so I can't change this behaviour easily). My
solution is to define a wrapper function FW(x), with two nested
functions, AW(x) and BW(x), which only call AB(x) if x has changed.
To make this all clear, here is my (failed) attempt:
#------begin code ---------
from ThirdPartyLibrary import F
from MyOtherModule import AB
def FW(x):
lastX = None
aLastX = None
bLastX = None
def AW(x):
if x != lastX:
lastX = x
# ^ Here's the problem. this doesn't actually
# change FW's lastX, but creates a new, local lastX
aLastX, bLastX = AB(x)
return aLastX
def BW(x):
if x != lastX:
lastX = x
# ^ Same problem
aLastX, bLastX = AB(x)
return bLastX
#finally, call the third party function and return its result
return F(AW, BW)
#-------- end code ---------
OK, here's my problem: How do I best store and change lastX, A(lastX)
and B(lastX) in FW's scope? This seems like it should be easy, but I'm
stuck. Any help would be appreciated!
-Brendan
--
Brendan Simons 10 1918
Brendan wrote: Hi everyone
I'm new to Python, so forgive me if the solution to my question should have been obvious.
....
Good question. For a thorough explanation see: http://www.python.org/dev/doc/devel/ref/naming.html
Simple version follows: OK, here's my problem: How do I best store and change lastX, A(lastX) and B(lastX) in FW's scope? This seems like it should be easy, but I'm stuck. Any help would be appreciated!
Assignments (i.e., binding names to objects) are always made in the local scope
(unless you've used the 'global' declaration, which I don't think can help you
here). So, for an even simpler demonstration of the problem see: def outer():
... b = 1
... def inner():
... b += 1
... print b
... inner()
... outer()
Traceback (most recent call last):
File "<input>", line 1, in ?
File "<input>", line 6, in outer
File "<input>", line 4, in inner
UnboundLocalError: local variable 'b' referenced before assignment
The solution is not to re-bind the identifier from the enclosing scope, but
rather to mutate the object that it references. This requires a mutable object,
such as a list:
def outer():
... b = [1] # bind b to a mutable object
... def inner():
... b[0] += 1
... print b[0]
... inner()
... outer()
2
HTH
Michael
I wish I had time to dig into your specific problem because it looks
interesting. But I think you might want to look at "python generators". I
beleive there is no reason that they can't yield a function. http://www.python.org/peps/pep-0255.html http://docs.python.org/ref/yield.html http://linuxgazette.net/100/pramode.html
James
On Sunday 03 April 2005 02:12 pm, Brendan wrote: Hi everyone
I'm new to Python, so forgive me if the solution to my question should have been obvious. I have a function, call it F(x), which asks for two other functions as arguments, say A(x) and B(x). A and B are most efficiently evaluated at once, since they share much of the same math, ie, A, B = AB(x), but F wants to call them independantly (it's part of a third party library, so I can't change this behaviour easily). My solution is to define a wrapper function FW(x), with two nested functions, AW(x) and BW(x), which only call AB(x) if x has changed.
To make this all clear, here is my (failed) attempt:
#------begin code ---------
from ThirdPartyLibrary import F from MyOtherModule import AB
def FW(x): lastX = None aLastX = None bLastX = None
def AW(x): if x != lastX: lastX = x # ^ Here's the problem. this doesn't actually # change FW's lastX, but creates a new, local lastX
aLastX, bLastX = AB(x) return aLastX
def BW(x): if x != lastX: lastX = x # ^ Same problem
aLastX, bLastX = AB(x) return bLastX
#finally, call the third party function and return its result return F(AW, BW)
#-------- end code ---------
OK, here's my problem: How do I best store and change lastX, A(lastX) and B(lastX) in FW's scope? This seems like it should be easy, but I'm stuck. Any help would be appreciated!
-Brendan -- Brendan Simons
--
James Stroud, Ph.D.
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095 http://www.jamesstroud.com/
On Sunday 03 April 2005 04:12 pm, Brendan wrote: from ThirdPartyLibrary import F from MyOtherModule import AB
def FW(x): lastX = None aLastX = None bLastX = None
I'm pretty sure your method will work if you just specify
that these are global:
def FW(x):
global lastX = None
global aLastX = None
global bLastX = None
OTOH, I'm biased against using module-level variables
for this kind of purpose and I think things that retain
state really ought to be class instances, so I'd probably replace
AB(x) with a callable object, and define two wrappers to access it
(untested):
class AB:
def __init__(self):
self._last_x = None
self._last_a = None
self._last_b = None
def __call__(self, x):
if x == self._last_x:
return self._last_a, self._last_b
else:
self._last_a, self._last_b = self.AB(x)
return self._last_a, self._last_b
def A(self, x):
return self(x)[0]
def B(self, x):
return self(x)[1]
def AB(self, x):
"""
This is where you compute your new values when needed.
"""
# something that computes a and b
return a,b
ab = AB()
Then you actually pass the methods ab.A and ab.B to your
library routine. This will usually work, though if it somehow
insists on an actual function instead of a callable, you can always
use wrapper functions.
This also has the advantage that you *can* process more than
one case at a time (i.e. if you have two different places where you
need this function to be called and you aren't sure what order
they'll be processed (or don't want to think about it), you can
give them different instances of AB to work with, and they'll
remember their previous calls separately.
Cheers,
Terry
--
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com
On 3 Apr 2005 14:12:48 -0700, "Brendan" <sp**********@yahoo.ca> wrote: Hi everyone
I'm new to Python, so forgive me if the solution to my question should have been obvious. I have a function, call it F(x), which asks for two other functions as arguments, say A(x) and B(x). A and B are most efficiently evaluated at once, since they share much of the same math, ie, A, B = AB(x), but F wants to call them independantly (it's part of a third party library, so I can't change this behaviour easily). My solution is to define a wrapper function FW(x), with two nested functions, AW(x) and BW(x), which only call AB(x) if x has changed.
You have several easy choices, that would not require you modifying
your program much.
1. Use the 'global' keyword to declare lastX, aLastX, and bLastX as
globals, then all functions will have access to them.
def FW(x):
global lastX, aLastX, bLastX
2. Use function attributes, which are just names attached to the
function using a '.'.
def FW(x):
#
# Function body here
#
return F(AW, BW)
FW.lastX = None
FW.aLastX = None
FW.bLastX = None
result = FW(x)
You will need to always include the FW. in front of those names.
3. Something else, that may help is you can return more than one value
at a time. Python has this neat feature that you can have multiple
items on either side of the '=' sign.
a,b,c = 1,2,3
same as:
a=1
b=2
c=3
And it also works with return statements so you can return multiple
value.
def abc(n):
return n+1, n+2, n+3
a,b,c = abc(0)
5. Choice 5 and above is to rewrite your function as a class. Names
in class's retain their values between calls and you can access those
values the same way as accessing function attributes.
Hope this helped.
Cheers,
Ron
To make this all clear, here is my (failed) attempt:
#------begin code ---------
from ThirdPartyLibrary import F from MyOtherModule import AB
def FW(x): lastX = None aLastX = None bLastX = None
def AW(x): if x != lastX: lastX = x # ^ Here's the problem. this doesn't actually # change FW's lastX, but creates a new, local lastX
aLastX, bLastX = AB(x) return aLastX
def BW(x): if x != lastX: lastX = x # ^ Same problem
aLastX, bLastX = AB(x) return bLastX
#finally, call the third party function and return its result return F(AW, BW)
#-------- end code ---------
OK, here's my problem: How do I best store and change lastX, A(lastX) and B(lastX) in FW's scope? This seems like it should be easy, but I'm stuck. Any help would be appreciated!
-Brendan
"Brendan" <sp**********@yahoo.ca> wrote in message
news:11**********************@l41g2000cwc.googlegr oups.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
Thanks for the tips. Making FW a callable class (choice 5) seems to be
a good (if verbose) solution. I might just wrap my temporary values in
a list [lastX, lastA, lastB] and mutate them as Michael suggests.
Thanks to Michael especially for the explanation of the name-binding
process that's at the heart of the issue.
The other choicess are not as helpful to me for the following reasons:
choice 1: I don't want the temporary values of lastA and lastB to be
global variables in my case as they are great big numeric arrays, and
I'd like their memory to be reclaimed after FW is done.
choice 2: I tried this without success. Using Micheal's example, I
would assume you mean something like this:
def outer():
b = 1
def inner():
outer.b += 1
print outer.b
inner()
outer()
Which gives me:
AttributeError: 'function' object has no attribute 'b'
Perhaps I misapplied this method?
choice 3: I know that Python can return multiple values in one line,
but I don't think that applies here. My library function F, is looking
for two separate function arguments
F -is- in fact an iterative optimizer that minimizes A on x (B is the
derivative of A). So yes, F will call A and B on mulitple 'x's. In
that case, it seems the mutable object trick is the way to go. Thanks.
I didn't follow your last sentence. What about the Python Cookbook? James Stroud Apr 3, 3:18 pm: I think you might want to look at "python generators".
I've seen discussion of generators before, but haven't invested the
time to understand them yet. This might be a good excuse.
On 3 Apr 2005 16:21:10 -0700, "Brendan" <sp**********@yahoo.ca> wrote: Thanks for the tips. Making FW a callable class (choice 5) seems to be a good (if verbose) solution. I might just wrap my temporary values in a list [lastX, lastA, lastB] and mutate them as Michael suggests. Thanks to Michael especially for the explanation of the name-binding process that's at the heart of the issue.
The other choicess are not as helpful to me for the following reasons:
choice 1: I don't want the temporary values of lastA and lastB to be global variables in my case as they are great big numeric arrays, and I'd like their memory to be reclaimed after FW is done.
Generally global variables should be avoided in python if you are
doing a large application. For smaller ones, they are ok, but they
are just a little slower than local variables.
You could use a classic class which is a good way to store a single
group of data. The 'del' will unbind a name from an object so the
objects can be garbage collected.
class data:
A = []
B = []
def countupdown():
for n in xrange(11):
data.A.append(n)
data.B.append(10-n)
print data.A
print data.B
countupdown()
# store data # Check out pickle module for this.
del data
choice 2: I tried this without success. Using Micheal's example, I would assume you mean something like this:
def outer():
def inner():
outer.b += 1
print outer.b
inner()
outer.b = 1 # <-- initialize here after function of same name
outer()
# save data method here
del outer # delete outer and it's attributes
"Brendan" <sp**********@yahoo.ca> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com... F -is- in fact an iterative optimizer that minimizes A on x (B is the derivative of A). So yes, F will call A and B on mulitple 'x's. In that case, it seems the mutable object trick is the way to go. Thanks.
As long as it calls A and B in that same order, rather than A several times
and B several times, then my code, fleshed out, will probably work. I didn't follow your last sentence. What about the Python Cookbook?
It is a book that is one place to find memoizer code which allows one to
save several x,f(x) pairs at once for later reuse. But you don't seem to
need it since an optimizer should never return to the exact same x except
by accident.
Terry J. Reedy This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Andy Jewell |
last post by:
Does anyone know of a way to dynamically reload all the imported modules of a
client module?
I'm writing a program that I have broken down into quite a few submodules, and
the 'configuration'...
|
by: Andy Baker |
last post by:
Hi there,
I'm learning Python at the moment and trying to grok the thinking behind
it's scoping and nesting rules.
I was googling for nested functions and found this Guido quote:...
|
by: Robert M. Gary |
last post by:
I'm curious what the ANSI C++ standard says about nested classes. I'm not
able to find where in the ANSI C++ standard this is addressed. The issue is
the accessibility of sibling nested classes....
|
by: Vinodh Kumar P |
last post by:
I abstract a Car, and the parts wihtin a car, with a C++ class.
Since only my version of class Car uses the classes defined for its parts,
is it a good practice to do like this?
class Car
{...
|
by: Mortos |
last post by:
I need some quick advice.
I just need to reference a containing class from the nested class. I'm
familiar with Java but C# is proving tricky.
public BigClass {
public int ID_BigClass = -99;
...
|
by: Carmella |
last post by:
Is it possible for a class to create an instance of a private nested class
which raises events and then listen for those events? In the example below,
when InnerClass sings, OuterClass should say...
|
by: Sean Givan |
last post by:
Hi. I'm new to Python, and downloaded a Windows copy a little while
ago. I was doing some experiments with nested functions, and ran into
something strange.
This code:
def outer():
val =...
|
by: jholg |
last post by:
Hi,
regarding automatically adding functionality to a class (basically taken
from the cookbook recipee) and Python's lexical nested scoping I have a question wrt this code:
#-----------------...
|
by: Joe, G.I. |
last post by:
Can anyone help me w/ a priority_queue. I'm generating MyEvent classes
and I put them on a priority_queue, but I don't know how to get them in
priority. The priority is the event w/ the smallest...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
| |