473,386 Members | 1,715 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

lambda closure question

What I want to do is pre-load functions with arguments by iterating
through a list like so:
class myclass: .... passdef func(self, arg): .... print argmylist = ["my", "sample", "list"]
for item in mylist: .... setattr(myclass, item, lamdba self: func(self, item))

This attaches a list of functions to the class, making them bound
methods when called from a class instance. The functions are all
similar except that they know their name through the item argument.
The lambda takes the underlying function and preloads it with its name,
and since lambdas support closures, it remembers the item variable that
was used to create it when it is actually called like so:
obj = myclass()
obj.list() list

That's great, since I can write a generic function that just needs to
know its name to make a slight modification to its behavior, then
attach it a bunch of times to a class under different names.

Unfortunately, it doesn't work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after the
lambda is created, the lambda still references the _variable_ not the
original _value_ and so gets the new value like so:
obj.sample() listobj.my()

list

At least, that's the explanation I'm deducing from this behavior.
Assuming that's the way Guido intended it to be (about as dynamic as it
can get), I'm at a loss to do what _I_ want it to do. In fact, I don't
think there's any way to generate the lambdas properly without coding
in the name as a literal string, since any attempt to use a variable
reference will always get modified as the loop iterates.

Am I missing something? Help.

Jul 18 '05 #1
27 2062
Ted Lilley wrote:
What I want to do is pre-load functions with arguments by iterating
through a list like so:
class myclass: ... passdef func(self, arg): ... print argmylist = ["my", "sample", "list"]
for item in mylist: ... setattr(myclass, item, lamdba self: func(self, item))
[snip]
Unfortunately, it doesn't work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after the lambda is created, the lambda still references the _variable_ not the
original _value_ and so gets the new value like so:
obj.sample() listobj.my()
list

At least, that's the explanation I'm deducing from this behavior.


And that's the correct explanation, chief.

Assuming that's the way Guido intended it to be (about as dynamic as it can get), I'm at a loss to do what _I_ want it to do. In fact, I don't think there's any way to generate the lambdas properly without coding
in the name as a literal string, since any attempt to use a variable
reference will always get modified as the loop iterates.


It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert in various
places within a function to print out the value of some local variable.
If you did that, you wouldn't want printvars to print the values at
the time it was bound, would you?

Anyways, this can be worked around, but I'd suppose it's not as
convenient as you'd like. (You could define crystalize outside the
loop, but I have it in the loop to keep it near the place where you
need it.)

.. mylist = ["my","sample","list"]
.. for item in mylist:
.. def crystalize(x):
.. return lambda self: func(self,x)
.. setattr(myclass,item,crystalize(item))

If you're hellbent on only using lambda, that can be done too:

.. setattr(myclass,item,(lambda x:(lambda self:
func(self,x)))(item))

You may not be aware of it, but what you're trying to do is called
"currying"; you might want to search the Python Cookbook for recipes on
it.
--
CARL BANKS

Jul 18 '05 #2
jfj
Carl Banks wrote:
Ted Lilley wrote:

Unfortunately, it doesn't work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after [...]

At least, that's the explanation I'm deducing from this behavior.

And that's the correct explanation, chief.


It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert in various
places within a function to print out the value of some local variable.
If you did that, you wouldn't want printvars to print the values at
the time it was bound, would you?


Allow me to disagree (and start a new "confused with closures" thread:)

We know that python does not have references to variables. To some
newcomers this may seem annoying but eventually they understand the
pythonic way and they do without them. But in the case of closures
python supports references!

Nested functions, seem to do two independent things:
1) reference variables of an outer local scoope
2) are functions bound dynamically to constants

These two are independent because in:
##############
def foo():
def nested():
print x
f = nested
x = 'sassad'
f()
x = 'aafdss'
f()
return f
##################

once foo() returns there is no way to modify 'x'!
It becomes a kind of constant.

So IMVHO, one will never need both features. You either want to
return a function "bound to a local value" *xor* "use a local
function which has access to locals as if they were globals".

Supposing the default behaviour was that python does what Carl
suggests (closures don't keep track of variables), would there
be an elegant pythonic way to implement "nested functions that
reference variables from their outer scope"? (although if find
this little useful and un-pythonic)

Personally, i think that this is a problem with the way lisp
and other languages define the term "closure". But python is
different IMO, and the ability to reference variables is not
useful.
cheers,

jfj
---------------
# the president
Jul 18 '05 #3

jfj wrote:
Carl Banks wrote:
Ted Lilley wrote:

Unfortunately, it doesn't work. It seems the closure keeps track ofthe variable fed to it dynamically - if the variable changes after [...]

At least, that's the explanation I'm deducing from this behavior.

And that's the correct explanation, chief.


It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert in various places within a function to print out the value of some local variable. If you did that, you wouldn't want printvars to print the values at the time it was bound, would you?


Allow me to disagree (and start a new "confused with closures"

thread:)
We know that python does not have references to variables. To some
newcomers this may seem annoying but eventually they understand the
pythonic way and they do without them. But in the case of closures
python supports references!


That's right. It's called Practicality beats purity.

The question is what's more important: to be able to use a nested
function to reference the outer scope, or to be able to use a nested
function as a closure inside the function it was defined in? (Both
approaches effectively allow using a nested function as a closure if
it's used after the function returns.)

The Gods decided, for practical reasons, the former was more important.
My experience bears this out: I find that about half the nested
functions I use are to reference an outer scope, half I return as a
closure. Only once or twice did I try to use a nested function inside
the defining function. I would guess this is more or less typical of
how nested functions are used. If so, it was the right decision.
--
CARL BANKS

Jul 18 '05 #4
jfj
Carl Banks wrote:
jfj wrote:
Carl Banks wrote:
Ted Lilley wrote:

Unfortunately, it doesn't work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after

[...]

At least, that's the explanation I'm deducing from this behavior.
And that's the correct explanation, chief.
It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert i
various
places within a function to print out the value of some local variable.
If you did that, you wouldn't want printvars to print the values at
the time it was bound, would you?


Allow me to disagree (and start a new "confused with closures"

thread:)
We know that python does not have references to variables. To some
newcomers this may seem annoying but eventually they understand the
pythonic way and they do without them. But in the case of closures
python supports references!

That's right. It's called Practicality beats purity.


Yes, but according to the python philosophy one could pass locals()
to the nested function and grab the values from there. Seems practical
for the rareness of this...
My experience bears this out: I find that about half the nested
functions I use are to reference an outer scope, half I return as a
closure. Only once or twice did I try to use a nested function inside
the defining function. I would guess this is more or less typical of
how nested functions are used. If so, it was the right decision.


The question is how many of the nested functions you use take advantage
of the fact that the deref'd variable is a *reference to a variable* and
not a *constant* (different constant for each definition of the nested
function of course).
Or, IOW, it seems very reasonable that if somebody wants to write the
"printvars()" function, he could simply pass locals().

I would accept this being the right decision if there was a statement
like "global var", called "deref var" with which nested funcs could
modify those variables. Then we could say:

#############
def foo():
def f1(y):
deref x
x = y
def f2():
print x
x=11
return f1, f2
####################
But one should go with OOP in that case instead.

Ogligatory Python 3000 suggestion:
I hope in python 3000, we'll get rid of CellObjects and insert
freevars at the consts of the function object at MAKE_CLOSURE.
jfj

Jul 18 '05 #5
Ted Lilley wrote:
What I want to do is pre-load functions with arguments by iterating
through a list like so:

class myclass:
... pass
def func(self, arg):
... print arg
mylist = ["my", "sample", "list"]
for item in mylist:
... setattr(myclass, item, lamdba self: func(self, item))

This attaches a list of functions to the class, making them bound
methods when called from a class instance.

obj = myclass()
obj.list()
list
Unfortunately, it doesn't work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after the
lambda is created, the lambda still references the _variable_ not the
original _value_ and so gets the new value like so:

obj.sample()
list
obj.my()


list


The closure isn't bound until the scope containing it is exited. A simple workaround is to bind item
as a default argument to the lambda:
for item in mylist:
setattr(myclass, item, lambda self, item=item: func(self, item))

You can also make a helper function that returns the closure, the closure will be bound each time
the helper returns:

def make_f(item):
def f(self): func(self, item)
return f

mylist = ["my", "sample", "list"]
for item in mylist:
setattr(myclass, item, make_f(item))

Kent
Jul 18 '05 #6
Carl Banks wrote:
You may not be aware of it, but what you're trying to do is called
"currying"; you might want to search the Python Cookbook for recipes on
it.


Or look for "partial function application" which has been argued to be
the correct term for this use... Also see PEP 309:

http://www.python.org/peps/pep-0309.html

With an appropriately defined "partial" (I've taken the one from the PEP
and added the descriptor machinery necessary to make it work as an
instancemethod):

-------------------- functional.py --------------------
class partial(object):
def __init__(*args, **kwargs):
self = args[0]
try:
self.fn = args[1]
except IndexError:
raise TypeError('expected 2 or more arguments, got ' %
len(args))
self.args = args[2:]
self.kwargs = kwargs
def __call__(self, *args, **kwargs):
if kwargs and self.kwargs:
d = self.kwargs.copy()
d.update(kwargs)
else:
d = kwargs or self.kwargs
return self.fn(*(self.args + args), **d)
def __get__(self, obj, type=None):
if obj is None:
return self
return partial(self, obj)

-------------------------------------------------------

py> class C(object):
.... pass
....
py> def func(self, arg):
.... return arg
....
py> lst = ['a', 'b', 'c']
py> for item in lst:
.... setattr(C, item, functional.partial(func, arg=item))
....
py> c = C()
py> c.a(), c.b(), c.c()
('a', 'b', 'c')

STeVe
Jul 18 '05 #7
Wow, a lot of great discussion. Almost a bit too much for me to
grasp...I do see two or more nuggets that really address my issue.

As a side note, I'm familiar with the term currying from a friend who
learned ML and Scheme quite some time ago. Not sure if that's the true
origin, but it was a sufficiently different context from Python (or at
least I thought) that I didn't want to rely on its meaning. I was also
sufficiently unsure of it's _exact_ meaning, since we're talking about
two slightly different models, that I didn't want to use the term for
that reason as well. It's gratifying to know that it was a relevant
concept afterall, the partial function application discussion
notwithstanding. It's also gratifying to see such a strong community
versed in functional programming styles. Although I've only started
working with FP in Python, it's been a useful tool for making my
programming simpler.

The first useful nugget is the crystalization method. I spent some
time thinking about the problem after I posted it and came up with the
same workaround, in fact, the exact same syntax. It's a bit inelegant,
but it gets the job done for what I want to do. I won't even attempt
to take a position in the debate about whether Python should work by
default the way it does or the way I want to use it. ;) Seems we have
well-spoken advocates for both sides.

The other nifty nugget is Kent's suggestion for using old-style Python
default arguments to capture the variable value. Since it looks
slightly more elegant I'm going to give it a shot.

I have to say, I was happily surprised by the volume and quality of
response to my little issue. Thanks everyone!

Ted

Jul 18 '05 #8
I replied a few minutes ago thanking everyone for their pointers. Very
interesting reading. I don't see my post yet, so I do hope it comes
through. I'm using a new newsreading service and don't yet have
confidence in it.

In any case, the addition of the default-setting argument in the lambda
works famously and is only a slight modification to my code. While I
don't think it's particularly intuitive (I would hate to be a
hypothetical programmer trying to puzzle out what my code does), it
gets the job done and is a heck of a lot easier than attaching the list
of attributes manually as I would've done without Python's FP
capabilities.

Thanks again,

Ted

Jul 18 '05 #9

jfj wrote:
Yes, but according to the python philosophy one could pass locals()
to the nested function and grab the values from there. Seems practical for the rareness of this...


First of all, I really don't agree that it's a rare need. I use it
pretty often.

Second of all, the whole point of referencing the outer scope is so you
don't *have* to pass stuff around. Saying that you can accomplish the
same thing by passing locals() isn't right, because the thing you were
accomplishing was not having to pass anything around.

Say you have a suite of functions, all of which are called by some main
function and each other, and all of which need to access a lot of the
same data. The best, most straightforward way to do it is to have the
common data be a local variable of the main function, and nest the
suite inside it. The other way to do it, passing around a common data
structure, add complexity and hurts performance.

And it's a pretty common situation; a lot of recursive algorithms can
make very good use of this.
--
CARL BANKS

Jul 18 '05 #10

Carl Banks wrote:
Say you have a suite of functions, all of which are called by some main function and each other, and all of which need to access a lot of the
same data. The best, most straightforward way to do it is to have the common data be a local variable of the main function, and nest the
suite inside it. The other way to do it, passing around a common data structure, add complexity and hurts performance.

This could use an example. It'll be a little mathematical; bear with
me.

Say you want to calculate a list of points of an iterated fractal.
Here's the idea: you have a set of linear transformations. You take
the origin (0,0) as the first point, and then apply each transformation
in turn to get a new point. You recursively apply each transformation
at each additional point, up to a certain depth.

What's the best way to write such a function? Using a nested function,
it's easy as pie. (Details may be a little wrong....)

.. def ifs(transformations, maxdepth):
.. def add_point(x,y,angle,depth):
.. ifspoints.append((x,y,angle))
.. if depth < maxdepth:
.. for t in transformations:
.. nx = x + t.x*cos(angle) - t.y*sin(angle)
.. ny = y + t.x*sin(angle) * t.y*cos(angle)
.. nangle = angle + t.angle
.. add_point(nx,ny,nangle,depth+1)
.. ifspoints = []
.. add_point(0.0, 0.0, 0.0, 0)
.. return ifspoints

If you didn't have the nested function, you'd have to pass not only
depth, but also maxdepth, transformations, and ifspoints around.

If you had something a little more complex than this, with more than
one nested function and more complex pieces of data you'd need to pass
around, the savings you get from not having to pass a data structure
around and referncing all that data though the structure can be quite a
lot.
--
CARL BANKS

Jul 18 '05 #11
jfj
Carl Banks wrote:

Say you want to calculate a list of points of an iterated fractal.
Here's the idea: you have a set of linear transformations. You take
the origin (0,0) as the first point, and then apply each transformation
in turn to get a new point. You recursively apply each transformation
at each additional point, up to a certain depth.
I like these kind of things. Ahhh, the best use out of one's computer.

What's the best way to write such a function? Using a nested function,
it's easy as pie. (Details may be a little wrong....)

. def ifs(transformations, maxdepth):
. def add_point(x,y,angle,depth):
. ifspoints.append((x,y,angle))
. if depth < maxdepth:
. for t in transformations:
. nx = x + t.x*cos(angle) - t.y*sin(angle)
. ny = y + t.x*sin(angle) * t.y*cos(angle)
. nangle = angle + t.angle
. add_point(nx,ny,nangle,depth+1)
. ifspoints = []
. add_point(0.0, 0.0, 0.0, 0)
. return ifspoints

If you didn't have the nested function, you'd have to pass not only
depth, but also maxdepth, transformations, and ifspoints around.

I see. Some people complained that you have to use "self." all the
time in methods:) If that was lifted the above would be done with
a class then?
The costly extra feature is this:
###############
def foo():
def f():
print x
x=1
f()
x=2
f()
return f
foo()()
#############
which prints '1 2 2'

The fractal code runs a little _slower_ because of this ability.
Although the specific program does not take advantage of it!
If you had something a little more complex than this, with more than
one nested function and more complex pieces of data you'd need to pass
around, the savings you get from not having to pass a data structure
around and referncing all that data though the structure can be quite a
lot.


Generally, I believe OOP is a superset of nested functions (as a
feature). Nested functions make sense to me as primary python
def statements which ``create new code objects with arbitary constants''

When I see :
###########
def foo(x):
def bar():
print x
return bar
###############
and the call:
xx = foo(1)

I imagine that python runs:
def bar():
print 1
xx=bar

But alas, it doesn't:(
Nooooooooo. It carries around a silly cell object for the
rest of its lifetime. see xx.func_closure.
At least, I think this is what happens...
jfj
Jul 18 '05 #12
Ted Lilley <te********@gmail.com> wrote:
As a side note, I'm familiar with the term currying from a friend who
learned ML and Scheme quite some time ago. Not sure if that's the true
origin, but it was a sufficiently different context from Python (or at
least I thought) that I didn't want to rely on its meaning. I was also
sufficiently unsure of it's _exact_ meaning,


The exact meaning is reasonably well explained, together with the
origins, on Wikipedia:

http://en.wikipedia.org/wiki/Currying

That meaning shouldn't change if applied to different computer languages.
I can understand the temptation to confuse partial application with
currying (for languages like Python which take tuples of arguments
by default, currying is one way to make partial application possible;
supplying default arguments is another), but nonetheless they are different
things.

- Dirk
Jul 18 '05 #13
"Carl Banks" <in**********@aerojockey.com> writes:
Say you have a suite of functions, all of which are called by some main
function and each other, and all of which need to access a lot of the
same data. The best, most straightforward way to do it is to have the
common data be a local variable of the main function, and nest the
suite inside it. The other way to do it, passing around a common data
structure, add complexity and hurts performance.


The third way to do it is to make the thing a class. Make all the
functions methods of the class, and all the data instance
variables. You may well want to make the main function the __call__
method of the class. In an OO environment, this may be a better, more
straightforward way than nesting fnctions.

See <URL:
http://aspn.activestate.com/ASPN/Coo...n/Recipe/52549 > for an
example of this.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Jul 18 '05 #14
Mike Meyer wrote:
"Carl Banks" <in**********@aerojockey.com> writes:
Say you have a suite of functions, all of which are called by some main function and each other, and all of which need to access a lot of the same data. The best, most straightforward way to do it is to have the common data be a local variable of the main function, and nest the
suite inside it. The other way to do it, passing around a common data structure, add complexity and hurts performance.
The third way to do it is to make the thing a class.


Which is kind of the same thing as passing a structure around, only
with a somewhat more convenient syntax. But yes.

Make all the
functions methods of the class, and all the data instance
variables. You may well want to make the main function the __call__
method of the class. In an OO environment, this may be a better, more
straightforward way than nesting fnctions.


There are good reasons for sometimes using a class, but
straightforwardness is, IMHO, not one of them.

You're writing a function (in the abstract sense: you are creating an
entity that you call with input to get output, and that has local
storage that doesn't need to exist afterwards). Is it more
straightforward to implement an (abstract) function with a function
object (i.e., the object that was designed exactly for that purpose),
or with a class (designed for a different purpose: to create new
types)? I'd definitely go with the former. Implementing an (abstract)
function as a class obscures its purpose.

I agree that there are many times when a class is a more appropriate
implementation of an (abstract) function, such as if your suite of
subfunctions has to rebind common variables, or if your (abstract)
function has so many return values it's better to define it as a class
and have the caller refer to the attributes. However, I'd say this
comes at the expense of straightforwardness (or, rather, it exchanges
one sort of striaghtforwardness for another sort judged more
important).
As for implementing an (abstract) function as a class just because
you're in an OO environment: that's just thinking backwards.

"OOP is the shizzle so I'm going to implement everything as a class,"
is simply the wrong way to think. There's a reason OOP is the shizzle:
because it's very often a good representation of the problem. But it
isn't always. And when it isn't, and when a better way exists (as in
this case), you should use the better way, even in the highly OO
environment. OOP is a means, not an end.
--
CARL BANKS

Jul 18 '05 #15

jfj wrote:
The costly extra feature is this:
###############
def foo():
def f():
print x
x=1
f()
x=2
f()
return f
foo()()
#############
which prints '1 2 2'

The fractal code runs a little _slower_ because of this ability.
Although the specific program does not take advantage of it!


True, in this case. (Although it's not that much slower; I think it's
only one extra dereference per access plus a little overhead.) But try
to extend your mind a bit and imagine that the recursive nested
function is called as part of a larger routine. Say, for example,
something that seeks a certain shape for the fractal.

.. def ifs(transformations,maxdepth):
.. def add_point(...):
.. ...
.. def test_shape():
.. ...
.. while True:
.. add_point(0,0,0,0)
.. x = test_shape()
.. if x < THRESHOLD:
.. break
.. transformations = adjust(transformation)

transformations gets rebound, so you'd need a reference to it.

I realize that this is getting more and more situationally specific (I
wouldn't yet say contrived, though; I have referenced changing bindings
a few times). Maybe you have a point.
--
CARL BANKS

Jul 18 '05 #16
Op 2005-02-19, jfj schreef <jf*@freemail.gr>:
Carl Banks wrote:
Ted Lilley wrote:

Unfortunately, it doesn't work. It seems the closure keeps track of
the variable fed to it dynamically - if the variable changes after

[...]

At least, that's the explanation I'm deducing from this behavior.

And that's the correct explanation, chief.


It is intended that way. As an example of why that is: consider a
nested function called "printvars()" that you could insert in various
places within a function to print out the value of some local variable.
If you did that, you wouldn't want printvars to print the values at
the time it was bound, would you?


Allow me to disagree (and start a new "confused with closures" thread:)

We know that python does not have references to variables. To some
newcomers this may seem annoying but eventually they understand the
pythonic way and they do without them. But in the case of closures
python supports references!

Nested functions, seem to do two independent things:
1) reference variables of an outer local scoope
2) are functions bound dynamically to constants

These two are independent because in:
##############
def foo():
def nested():
print x
f = nested
x = 'sassad'
f()
x = 'aafdss'
f()
return f
##################

once foo() returns there is no way to modify 'x'!
It becomes a kind of constant.


In this particular case yes. But not in general, what about
this:
def F(): .... l = []
.... def pop():
.... return l.pop()
.... def push(e):
.... l.append(e)
.... return pop, push
.... pop, push = F()
push(1)
pop() 1 push(2)
push(3)
pop() 3 pop()

2

--
Antoon Pardon
Jul 18 '05 #17
jfj
Antoon Pardon wrote:
Op 2005-02-19, jfj schreef <jf*@freemail.gr>:
once foo() returns there is no way to modify 'x'!
It becomes a kind of constant.

In this particular case yes. But not in general, what about
this:

def F():


... l = []
... def pop():
... return l.pop()
... def push(e):
... l.append(e)
... return pop, push
...


Others will point this out, but if I'm fast enough...

This does not change the object referenced by l.
It calls methods of it and because it is mutable the containts
of the list are modified.
'l' is a list at address, 0xXXXX and that can never change once
F() has returned.
jfj
Jul 18 '05 #18
Op 2005-02-21, jfj schreef <jf*@freemail.gr>:
Antoon Pardon wrote:
Op 2005-02-19, jfj schreef <jf*@freemail.gr>:
once foo() returns there is no way to modify 'x'!
It becomes a kind of constant.

In this particular case yes. But not in general, what about
this:

>def F():


... l = []
... def pop():
... return l.pop()
... def push(e):
... l.append(e)
... return pop, push
...


Others will point this out, but if I'm fast enough...

This does not change the object referenced by l.
It calls methods of it and because it is mutable the containts
of the list are modified.
'l' is a list at address, 0xXXXX and that can never change once
F() has returned.


I'm sorry but in my understanding of english mutating an object
is changing or modifying it. Yes it is stil the same list but
that list was not unmodified.

But I'll get back at what seems you actually wanted to say:
That there is no way to rebind 'x' or in my case 'l' and
with that I have to agree although I personnaly find that
a lack in python

--
Antoon Pardon
Jul 18 '05 #19
> But I'll get back at what seems you actually wanted to say:
That there is no way to rebind 'x' or in my case 'l' and
with that I have to agree although I personnaly find that
a lack in python


It's not only that way in python, but in java too. So it seems that there is
a fundamental principle behind it: In a language that allows sideeffects,
these will actually happen.

If you're after side-effect free programming, I recommend using a functional
programming language like ocaml or haskell. In these, you can't mutate
objects at all, only recreate them and rebind them to new variables. This
prevents whole classes of errors - but of course it also introduces all
kinds of other constraints on your programming style, e.g. using monads and
so on.

--
Regards,

Diez B. Roggisch
Jul 18 '05 #20
Antoon Pardon wrote:
But I'll get back at what seems you actually wanted to say:
That there is no way to rebind 'x' or in my case 'l' and
with that I have to agree although I personnaly find that
a lack in python


'no way' is a bit strong. You can use hacks such as the one I posted a
couple of weeks back:
import hack
def F(): l = 'hello there'
def get():
return l
return hack.mksetter(lambda: l), get
set, get = F()
get() 'hello there' set('testing') 'testing' get()

'testing'

'no official, supported, or portable way' would be more accurate.

I've never actually felt the need to set variables from inside a nested
function, and I wouldn't use a hack like this in production code unless
there was a *very* good reason for it, but since I figured out how to
actually do it I'm suprised just how many things could actually be
simplified if there was an official way to do this.
Jul 18 '05 #21
Op 2005-02-21, Diez B. Roggisch schreef <de*********@web.de>:
But I'll get back at what seems you actually wanted to say:
That there is no way to rebind 'x' or in my case 'l' and
with that I have to agree although I personnaly find that
a lack in python


It's not only that way in python, but in java too. So it seems that there is
a fundamental principle behind it: In a language that allows sideeffects,
these will actually happen.

If you're after side-effect free programming, I recommend using a functional
programming language like ocaml or haskell. In these, you can't mutate
objects at all, only recreate them and rebind them to new variables. This
prevents whole classes of errors - but of course it also introduces all
kinds of other constraints on your programming style, e.g. using monads and
so on.


I have the impression that you misunderstood me. I'm not after a
side-effect free language. I just think python could be nicer in
allowing some side-effects.

--
Antoon Pardon
Jul 18 '05 #22
"Diez B. Roggisch" <de*********@web.de> writes:
It's not only that way in python, but in java too. So it seems that there is
a fundamental principle behind it: In a language that allows sideeffects,
these will actually happen.


Can you even have nested functions in Java? Algol-60 did things the
way you'd expect, i.e. you can modify the outer variable from the
inner scope.
Jul 18 '05 #23
Paul Rubin wrote:
"Diez B. Roggisch" <de*********@web.de> writes:
It's not only that way in python, but in java too. So it seems that there
is a fundamental principle behind it: In a language that allows
sideeffects, these will actually happen.


Can you even have nested functions in Java? Algol-60 did things the
way you'd expect, i.e. you can modify the outer variable from the
inner scope.


Not nested functions, but closures in anonymous inner classes - which can
reference only final variables, thus creating the same effect as the
scoping rules of python.

--
Regards,

Diez B. Roggisch
Jul 18 '05 #24
> I have the impression that you misunderstood me. I'm not after a
side-effect free language. I just think python could be nicer in
allowing some side-effects.


Yeah, seems as if I somehow added an inadvertent "not" somewhere in my train
of thoughts while reading (and hopfully comprehending...) your post. Sorry.
--
Regards,

Diez B. Roggisch
Jul 18 '05 #25
jfj
Carl Banks wrote:
transformations gets rebound, so you'd need a reference to it.


That certainly is an application. I guess it depends on one's
programming background.

I'd only use nested (function, class) definition to accomplish
such a feature:

########################
def genclass(x,y):
class myclass:
M = x
def f(self, z):
return self.M + y + z
return myclass

A=genclass(1,2)
a=A()
#########################

where i would prefer python to expand this as a template to:

class myclass:
M = 1
def f(self, z):
return self.M + 2 + z
A = myclass
a = A()

IOW, I'd like nested (function, class) definitions to
be used *only* for dynamic code generation with runtime
constants, and OOP *forced* for other applications like
the fractal example:)

jf
---------------
# if you're dissatisfied with the situation on the planet
# slow down the circulation of money

Jul 18 '05 #26
Antoon Pardon wrote:
def F():

... l = []
... def pop():
... return l.pop()
... def push(e):
... l.append(e)
... return pop, push
...


Just a side note to point out that another way of writing this is:

py> def F():
.... l = []
.... return l.pop, l.append
....

You'll get the same behavior:

py> pop, push = F()
py> push(1)
py> pop()
1
py> push(2)
py> push(3)
py> pop()
3
py> pop()
2

Hooray for bound methods! ;)

STeVe
Jul 18 '05 #27
"Ted Lilley" <te********@gmail.com> writes:
What I want to do is pre-load functions with arguments by iterating
through a list like so:
class myclass: ... passdef func(self, arg): ... print argmylist = ["my", "sample", "list"]
for item in mylist:

... setattr(myclass, item, lamdba self: func(self, item))


I just found myself doing something similar to deal with unittest.py's
test loaders/runners, which have to be able to find attributes on a
class before the class is instantiated.

def addItemStateTransTest(klass):
"""
For each item generator and transition test, add a method to klass
to test that combo.
"""
for ig_name in klass.item_generators:
for tt_name in klass.transition_tests.keys():
test_name = "test" + ig_name + tt_name
test_fun = (lambda self,
ig_name=ig_name, tt_name=tt_name:
self.doTestItemStateTrans(ig_name, tt_name))
setattr(klass, test_name, test_fun)

--
Karl Anderson kr*@monkey.org http://monkey.org/~kra/
Jul 18 '05 #28

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Roy Smith | last post by:
My apologies for a somewhat silly posting, but after 6 years of hacking Python, I finally found a use for lambda! I wanted to write a unit test to prove that a given dictionary does not have a...
8
by: Ian McMeans | last post by:
I was bitten by a bug today that depended on how lambda works. It took me quite a while to realize what was going on. First, I made multiple lambda functions inside a loop, each of which...
53
by: Oliver Fromme | last post by:
Hi, I'm trying to write a Python function that parses an expression and builds a function tree from it (recursively). During parsing, lambda functions for the the terms and sub-expressions...
31
by: Jason Zheng | last post by:
I'm wondering why python still has limited lambda support. What's stopping the developers of python to support more lisp-like lambda function?
181
by: Tom Anderson | last post by:
Comrades, During our current discussion of the fate of functional constructs in python, someone brought up Guido's bull on the matter: http://www.artima.com/weblogs/viewpost.jsp?thread=98196 ...
25
by: Russell | last post by:
I want my code to be Python 3000 compliant, and hear that lambda is being eliminated. The problem is that I want to partially bind an existing function with a value "foo" that isn't known until...
267
by: Xah Lee | last post by:
Python, Lambda, and Guido van Rossum Xah Lee, 2006-05-05 In this post, i'd like to deconstruct one of Guido's recent blog about lambda in Python. In Guido's blog written in 2006-02-10 at...
26
by: brenocon | last post by:
Hi all -- Compared to the Python I know and love, Ruby isn't quite the same. However, it has at least one terrific feature: "blocks". Whereas in Python a "block" is just several lines of...
11
by: ssecorp | last post by:
I am never redefining the or reassigning the list when using validate but since it spits the modified list back out that somehow means that the modified list is part of the environment and not the...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.