Hello,
I would like to associate a local namespace with a lambda function. To
be more specific, here is exactly what I would want:
def foo():
a = 1
f = lambda x : a*x
return f
then if "f1 = foo()", I get a function whose parameter "a" is not in
the global scope. But my functions are not to be hard-coded. I naively
expected the following to work:
def foo(funcstring):
a = 1
f = eval(funcstring)
return f
but "f2 = foo( 'lambda x : a*x' )" won't work: "f2()" will look for
"a" in the globals.
Looking at the documentation (I did!), I was then certain replacing
the evaluation with the following would work:
f = eval(funcstring, globals(), locals())
Or, while we're at it, evaluating the whole thing outside of function
"foo":
f = eval('lambda x : a*x', globals(), {'a' : 1})
Ooops! the new function still looks for "a" in the globals... Although
I could not find any documentation about the fact, it seems the
"local" argument to "eval" has no effect in the above cases!
So for now, I'm doing something like
f = eval('lambda x : a*x', {'a' : 1})
but then my function looses access to the globals.
I know that only the very first case above gives me a function whose
"fun_closure" attribute is not "None". But still I cannot see where I
go wrong.
Thank you,
JSeb 4 2007 js**@cs.mcgill.ca (Jean-Sébastien Bolduc) wrote in message news:<56**************************@posting.google. com>... Hello,
I would like to associate a local namespace with a lambda function. To be more specific, here is exactly what I would want:
def foo(): a = 1 f = lambda x : a*x return f
then if "f1 = foo()", I get a function whose parameter "a" is not in the global scope. But my functions are not to be hard-coded. I naively expected the following to work:
def foo(funcstring): a = 1 f = eval(funcstring) return f
but "f2 = foo( 'lambda x : a*x' )" won't work: "f2()" will look for "a" in the globals.
Looking at the documentation (I did!), I was then certain replacing the evaluation with the following would work:
f = eval(funcstring, globals(), locals())
Or, while we're at it, evaluating the whole thing outside of function "foo":
f = eval('lambda x : a*x', globals(), {'a' : 1})
Ooops! the new function still looks for "a" in the globals... Although I could not find any documentation about the fact, it seems the "local" argument to "eval" has no effect in the above cases!
So for now, I'm doing something like
f = eval('lambda x : a*x', {'a' : 1})
but then my function looses access to the globals.
I know that only the very first case above gives me a function whose "fun_closure" attribute is not "None". But still I cannot see where I go wrong.
Thank you,
JSeb
**kwa** is the solution!
In your factory-function *foo* you have to declare *a*
keywordarguement which is initialized with a. def foo():
.... a=1
.... f=lambda x,a=a:a*x
.... return f
f1=foo() f1(3)
3
A global *a* doesn't affect your function. a=1000 f1(3)
3
but you even can get influence to *a*: f1(3,a=100)
300
or f1(3,100)
300
And this works too, even if you generate a lambda-function
as adhoc-function in the global scope:
!! You have to define *a* as first !! a=100 f2=lambda x,a=a:a*x f2(3)
300
To change the global *a* doesn't affect your lambda-function! a=0 f2(3)
300
But you can give your function the additional information. f2(3,a=1)
3
or more traditional f2(3,1)
3
And the default kwa will stay resident. f2(3)
300
Regards
Peter
> **kwa** is the solution! In your factory-function *foo* you have to declare *a* keywordarguement which is initialized with a.
def foo():
... a=1 ... f=lambda x,a=a:a*x ... return f
Not exactly what I'm looking for, I'm afraid. A more complete picture
is this: I'm writing a class such as this:
class Foo:
def __init__(self, fnc, **params):
...
def evaluate(self, val)
...
That has to be instantiated as, e.g.:
x = Foo( 'lambda x : a*x', dict( a = 2. ) )
so that "x.evaluate( 5. )" will return, in this case, "2.*5.".
The approach you describe will certainly work, but the thing is that
this class will have to be used by people who don't necessarily know
Python (yet). So I would really like the lambda function's parameter
list to always be the same, whatever you put on its RHS.
Once again, I don't understand why the "eval", as described above with
"globals" and "locals" arguments specified, will not work. Is there a
way to modify a function's closure?
Thanks,
JSeb
Jean-S?bastien Bolduc wrote:
... is this: I'm writing a class such as this:
class Foo: def __init__(self, fnc, **params): ... def evaluate(self, val) ...
That has to be instantiated as, e.g.:
x = Foo( 'lambda x : a*x', dict( a = 2. ) )
Hmmm. 'a' is NOT a local in that lambda -- it's a global. locals
are [a] arguments, plus [b] variables that get re-bound within the
function (which, in a lambda, means only control variables used in
list comprehensions), PERIOD. That, if you want, is the DEFINITION
of "local variable" in Python.
So, that dict had better be in the GLOBALS, or else variable 'a' will
of course not be fond.
so that "x.evaluate( 5. )" will return, in this case, "2.*5.".
The approach you describe will certainly work, but the thing is that this class will have to be used by people who don't necessarily know Python (yet). So I would really like the lambda function's parameter list to always be the same, whatever you put on its RHS.
Once again, I don't understand why the "eval", as described above with "globals" and "locals" arguments specified, will not work. Is there a way to modify a function's closure?
You may play with closures, yes (not really modifying a function's
closure but rather building a new function object with a code taken
from one place and a closure from another, say), but I'm not sure it
would help you.
Consider the following...: import dis thefunc = lambda x: a * x dis.dis(thefunc)
1 0 LOAD_GLOBAL 0 (a)
3 LOAD_FAST 0 (x)
6 BINARY_MULTIPLY
7 RETURN_VALUE
Even if you're not familiar with Python's bytecode, I hope the simple
disassembly above is clear enough anyway: the value of 'a' is "loaded"
(onto the Python virtual machine's stack) as a *GLOBAL*, the value of
'x' is loaded via the "fast" (locals-only) route, then the multiply
happens (using the two top entries of the stack and pushing the result)
and the result is returned as the function's value.
Now, since you have the lambda available AS A STRING, you may consider:
def ff(a=99):
.... return lambda x: x * a
.... thefunc1 = ff() dis.dis(thefunc1)
2 0 LOAD_FAST 0 (x)
3 LOAD_DEREF 0 (a)
6 BINARY_MULTIPLY
7 RETURN_VALUE
Here, the Python compiler knows that a IS a local (an argument, in
this example) in an enclosing function, therefore it loads 'a' with
LOAD_DEREF, *NOT* with LOAD_GLOBAL. Because of this, and of this
only, thefunc1.closure does matter (it's a cell referencing that
int value, 99 in this case). Perhaps that might help, though it
still takes QUITE a bit of work to exploit it.
However, I do not understand why you should fight "the system" (the
fact that the Python compiler KNOWS that 'a' is global in the first
and simpler use) -- why not just supply that dict you have as (some
part of) the globals...?
Alex js**@cs.mcgill.ca (Jean-S?bastien Bolduc) wrote in message news:<56**************************@posting.google. com>... **kwa** is the solution!
In your factory-function *foo* you have to declare *a* keywordarguement which is initialized with a.
>> def foo(): ... a=1 ... f=lambda x,a=a:a*x ... return f
Not exactly what I'm looking for, I'm afraid. A more complete picture is this: I'm writing a class such as this:
class Foo: def __init__(self, fnc, **params): ... def evaluate(self, val) ...
That has to be instantiated as, e.g.:
x = Foo( 'lambda x : a*x', dict( a = 2. ) )
so that "x.evaluate( 5. )" will return, in this case, "2.*5.".
The approach you describe will certainly work, but the thing is that this class will have to be used by people who don't necessarily know Python (yet). So I would really like the lambda function's parameter list to always be the same, whatever you put on its RHS.
Once again, I don't understand why the "eval", as described above with "globals" and "locals" arguments specified, will not work. Is there a way to modify a function's closure?
Thanks, JSeb
Sorry, I missunderstood you.
Since your last post I learned the further more two
parameters of the eval-function. I'm even not sure
if I checked the problem entirely, but let me try to
explain what I think I may have understood.
In the following function the eval-statement doesn't
really need the locals() to evaluate the lambda-function.
It really needs to tell the lambda where is its parent's
namespace - what is by default the modules-namespace which
one calls *globals()* - where to search for variables when
not found in the locals(). def new_fn(fn_string):
.... a=99999
.... print locals()
.... local_fun=eval(fn_string,globals(),locals())
.... return local_fun
....
I think the locals() are always the variables of a function's
body - in the above case of the function *new_fn*.
f=new_fn('lambda x:(x*a,locals())')
will show that:
{'a': 99999, 'fn_string': 'lambda x:(x*a,locals())'}
So the following let us know what locals() means
for the lambda-function: a=0 f(10)
(0, {'x': 10})
But *a* is found in the global-scope.
I'm not sure if this really helps you and the only
workaround for me is something I posted to you the last time.
What makes me more confused is the following example, where
the lambda-function is declared explicitly.
def new_fn():
.... a=99999
.... print locals()
.... local_fun=lambda x:(x*a,locals())
.... return local_fun
.... f=new_fn()
{'a': 99999} a=0 f(10)
(999990, {'a': 99999, 'x': 10})
But I think that's what you did already.
PS: I here someone whispering something of *nested scopes*.
Regards
Peter This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Peter Luciak |
last post by:
Hi,
I need to do something like this:
def my():
a,b=1,2
func = "lambda x: a*x+b"
map(eval(func),)
my()
|
by: robcarlton |
last post by:
hi everybody
I've written this function to make a list of all of an objects
attributes and methods (not for any reason, I'm just learning)
def list_members(obj)
l = dir(obj)
return map(lambda...
|
by: dm_dal |
last post by:
I have a control on my webform that I am binding to a dataset. The issue
is, the field value in the dataset is encrypted and I am trying to decrypt
it during the binding process:
Example:
...
|
by: Jens |
last post by:
Hi,
has anyone an idea why the following code does not work.
s = """
def a(n):
return n*n
|
by: Pauljh |
last post by:
Hi All,
I'm running some javascript over a server side generated web page
and have multiple generated empty select statements, that I want to
populate when the page is loaded. As HTML doesn't do...
|
by: FAQ server |
last post by:
-----------------------------------------------------------------------
FAQ Topic - When should I use eval?
-----------------------------------------------------------------------
The ` eval() `...
|
by: Florian Loitsch |
last post by:
hi,
What should be the output of the following code-snippet?
===
var x = "global";
function f() {
var x = 0;
eval("function x() { return false; }");
delete x;
alert(x);
}
|
by: Gordon |
last post by:
I have a script that creates new objects based on the value of a form
field. Basically, the code looks like this.
eval ('new ' + objType.value + '(val1, val2, val3');
objType is a select with...
|
by: mag |
last post by:
I have a make file that executes a perl script that takes PERL as an eval.
The script executes the eval() function via an arguement to the script
like this:
target:
script $(ARGUMENT)
...
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
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: 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: 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: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: Shćllîpôpď 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
|
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...
| |