Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Closures in leu of pointers?

Reply
Thread Tools

Closures in leu of pointers?

 
 
cts.private.yahoo@gmail.com
Guest
Posts: n/a
 
      06-29-2013
Hi,

I'd like to use closures to set allow a subroutine to set variables in its caller, in leu of pointers. But I can't get it to work. I have the following test pgm, but I can't understand its behaviour:

It uses a function p2() from the module modules.closure1b:

def p2 (proc):
proc ("dolly")

I thought the following worked like I expected it to:


from modules.closures1b import p2

def p1(msg1):
msg3 = "world"
print "p1: entered: ", msg1
def p11(msg2):
print "p11: entered: ", msg2
print msg1 + msg2 + msg3
print p2 (p11)

p1('hello')

$ python closures1c.py
p1: entered: hello
p11: entered: dolly
hellodollyworld
None

In other words, p1() is passed "hello" for msg1, "world" goes to the local msg3 and then p11() is invoked out of a remote module and it can access not only its own argument (msg2) but also the variables local to p1(): "hellodollyworld".

But if I try to set the variable local to p1(), all of a sudden python seems to forget everything we agreed on.

If I add this line to the script above:
msg3 = "goodbye"
as follows:

from modules.closures1b import p2

def p1(msg1):
msg3 = "world"
print "p1: entered: ", msg1
def p11(msg2):
print "p11: entered: ", msg2
print msg1 + msg2 + msg3
msg3 = "goodbye" # <- new
print p2 (p11)

p1('hello')

then all of a sudden, I get this:

p1: entered: hello
p11: entered: dolly
Traceback (most recent call last):
File "closures1c.py", line 13, in <module>
p1('hello')
File "closures1c.py", line 11, in p1
print p2 (p11)
File "/home/mellman/eg/python/modules/closures1b.py", line 2, in p2
proc ("dolly")
File "closures1c.py", line 9, in p11
print msg1 + msg2 + msg3
UnboundLocalError: local variable 'msg3' referenced before assignment


Huh? msg3 isn't more referenced than it was before!

Can anyone explain this to me?




 
Reply With Quote
 
 
 
 
Fábio Santos
Guest
Posts: n/a
 
      06-29-2013
On 29 Jun 2013 10:38, <(E-Mail Removed)> wrote:
>
> Hi,
>
> I'd like to use closures to set allow a subroutine to set variables in

its caller, in leu of pointers. But I can't get it to work. I have the
following test pgm, but I can't understand its behaviour:
>
> It uses a function p2() from the module modules.closure1b:
>
> def p2 (proc):
> proc ("dolly")
>
> I thought the following worked like I expected it to:
>
>
> from modules.closures1b import p2
>
> def p1(msg1):
> msg3 = "world"
> print "p1: entered: ", msg1
> def p11(msg2):
> print "p11: entered: ", msg2
> print msg1 + msg2 + msg3
> print p2 (p11)
>
> p1('hello')
>
> $ python closures1c.py
> p1: entered: hello
> p11: entered: dolly
> hellodollyworld
> None
>
> In other words, p1() is passed "hello" for msg1, "world" goes to the

local msg3 and then p11() is invoked out of a remote module and it can
access not only its own argument (msg2) but also the variables local to
p1(): "hellodollyworld".
>
> But if I try to set the variable local to p1(), all of a sudden python

seems to forget everything we agreed on.
>
> If I add this line to the script above:
> msg3 = "goodbye"
> as follows:
>
> from modules.closures1b import p2
>
> def p1(msg1):
> msg3 = "world"
> print "p1: entered: ", msg1
> def p11(msg2):
> print "p11: entered: ", msg2
> print msg1 + msg2 + msg3
> msg3 = "goodbye" # <- new
> print p2 (p11)
>
> p1('hello')
>
> then all of a sudden, I get this:
>
> p1: entered: hello
> p11: entered: dolly
> Traceback (most recent call last):
> File "closures1c.py", line 13, in <module>
> p1('hello')
> File "closures1c.py", line 11, in p1
> print p2 (p11)
> File "/home/mellman/eg/python/modules/closures1b.py", line 2, in p2
> proc ("dolly")
> File "closures1c.py", line 9, in p11
> print msg1 + msg2 + msg3
> UnboundLocalError: local variable 'msg3' referenced before assignment
>
>
> Huh? msg3 isn't more referenced than it was before!
>
> Can anyone explain this to me?


The fact that msg3 is assigned to in that scope makes it a local variable.
It doesn't matter if the assignment happens later. Python will treat it as
local, and so won't look for it outside the local scope/closure.

The fix is to declare msg3 as global, I think.

 
Reply With Quote
 
 
 
 
Peter Otten
Guest
Posts: n/a
 
      06-29-2013
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> I'd like to use closures to set allow a subroutine to set variables in its
> caller, in leu of pointers.


"leu"? Must be a Fench word

> But I can't get it to work. I have the
> following test pgm, but I can't understand its behaviour:
>
> It uses a function p2() from the module modules.closure1b:
>
> def p2 (proc):
> proc ("dolly")
>
> I thought the following worked like I expected it to:
>
>
> from modules.closures1b import p2
>
> def p1(msg1):
> msg3 = "world"
> print "p1: entered: ", msg1
> def p11(msg2):
> print "p11: entered: ", msg2
> print msg1 + msg2 + msg3
> print p2 (p11)
>
> p1('hello')
>
> $ python closures1c.py
> p1: entered: hello
> p11: entered: dolly
> hellodollyworld
> None
>
> In other words, p1() is passed "hello" for msg1, "world" goes to the local
> msg3 and then p11() is invoked out of a remote module and it can access
> not only its own argument (msg2) but also the variables local to p1():
> "hellodollyworld".
>
> But if I try to set the variable local to p1(), all of a sudden python
> seems to forget everything we agreed on.
>
> If I add this line to the script above:
> msg3 = "goodbye"
> as follows:
>
> from modules.closures1b import p2
>
> def p1(msg1):
> msg3 = "world"
> print "p1: entered: ", msg1
> def p11(msg2):
> print "p11: entered: ", msg2
> print msg1 + msg2 + msg3
> msg3 = "goodbye" # <- new
> print p2 (p11)
>
> p1('hello')
>
> then all of a sudden, I get this:
>
> p1: entered: hello
> p11: entered: dolly
> Traceback (most recent call last):
> File "closures1c.py", line 13, in <module>
> p1('hello')
> File "closures1c.py", line 11, in p1
> print p2 (p11)
> File "/home/mellman/eg/python/modules/closures1b.py", line 2, in p2
> proc ("dolly")
> File "closures1c.py", line 9, in p11
> print msg1 + msg2 + msg3
> UnboundLocalError: local variable 'msg3' referenced before assignment
>
>
> Huh? msg3 isn't more referenced than it was before!
>
> Can anyone explain this to me?


You picked the most obnoxious variable names I can think of, but the actual
problem is simple:

Python statically determines the scope of a variable. If you rebind a name
it becomes a local variable unless you explicitly declare it as global or --
in Python 3 -- as nonlocal. For example:

Wrong:

>>> def outer():

.... n = 0
.... def inner():
.... print(n)
.... n += 1
.... return inner
....
>>> outer()()

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in inner
UnboundLocalError: local variable 'n' referenced before assignment

With nonlocal declaration (Python 3 only):
>>> def outer():

.... n = 0
.... def inner():
.... nonlocal n
.... print(n)
.... n += 1
.... return inner
....
>>> f = outer()
>>> f()

0
>>> f()

1
>>> f()

2

With a mutable variable as a pseudo-namespace (workaround for Python 2):

>>> def outer():

.... n = [0]
.... def inner():
.... print n[0]
.... n[0] += 1
.... return inner
....
>>> f = outer()
>>> f()

0
>>> f()

1


 
Reply With Quote
 
cts.private.yahoo@gmail.com
Guest
Posts: n/a
 
      06-29-2013
Well, it would have been French if I had spelled it right - since you force me overcome my laziness, I see I should have spelled it lieu ...

Thank you. You reminded me of the (weak) workaround of using arrays and confirmed my suspicion that I although I can read the variable, I won't be able to write to it. I still don't understand why not, though...

As for python 3 ... "nonlocal"? I see I'm not alone in picking obnoxious names ...
 
Reply With Quote
 
cts.private.yahoo@gmail.com
Guest
Posts: n/a
 
      06-29-2013
Alas, one reason it's a weak workaround is that it doesn't work - at least, not how I wish it would:


$ cat ptrs

x = 34

def p1 (a1):

a1[0] += 12

p1 ([x])

print (x)

$ python ptrs
34
 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      06-29-2013
(E-Mail Removed) wrote:

> As for python 3 ... "nonlocal"? I see I'm not alone in picking obnoxious
> names ...


tous chez...

> Alas, one reason it's a weak workaround is that it doesn't work - at
> least, not how I wish it would:


> $ cat ptrs
>
> x = 34
>
> def p1 (a1):
>
> a1[0] += 12
>
> p1 ([x])
>
> print (x)
>
> $ python ptrs
> 34


That doesn't work with 'nonlocal' either.

You can compare Python's names with (automatically dereferenced and
garbage-collected) pointers, but there is no way to have a name refer to
another name. The C-like

f(var *value)
{
value = ...
}

is the only way to pass a variable in Python. There is no way to emulate

f(var **value)
{
*value = ...
}

When this came up a few days ago I linked to

http://learntofish.wordpress.com/201...ll-by-sharing/

but I was actually looking for the classic, so there:

http://python.net/~mwh/hacks/objectthink.html

PS: If you're reading this and love the French language -- I am deeply sorry
for the pain I'm causing you...

 
Reply With Quote
 
cts.private.yahoo@gmail.com
Guest
Posts: n/a
 
      06-29-2013
"PS: If you're reading this and love the French language -- I am deeply sorry
for the pain I'm causing you..."

It's obviously a team effort...

My French ain't so hot, either. I had to google your "tout chez" until I ran into the explanation:

hallo also ich gucke super gerne two and a half men und da wird öfters tout chez (keine ahnung ob es so geschrieben wird) gesagt. ich hab gegooglet aber nichts gefunden. ich habs auch überstzen lassen aber da kommt nur raus "alles bei"...das wirds ja wohl nicht sein^^ könnte mir also jemand sagen was es genau bedeutet wenn man das sagt?

The answer for us TV-challenged non-views:

Es heißt: "touché"
 
Reply With Quote
 
Michael Torrie
Guest
Posts: n/a
 
      06-29-2013
On 06/29/2013 05:44 AM, (E-Mail Removed) wrote:
> Alas, one reason it's a weak workaround is that it doesn't work - at least, not how I wish it would:
>
>
> $ cat ptrs
>
> x = 34
>
> def p1 (a1):
>
> a1[0] += 12
>
> p1 ([x])
>
> print (x)
>
> $ python ptrs
> 34


you'll have to use it more like this (and also changing your names to be
a bit more sane):

x = [ 34, ]

def test_func( out ):
out[0] += 12

test_func(x)

print (x)

 
Reply With Quote
 
Michael Torrie
Guest
Posts: n/a
 
      06-29-2013
On 06/29/2013 05:21 AM, (E-Mail Removed) wrote:
> Thank you. You reminded me of the (weak) workaround of using arrays
> and confirmed my suspicion that I although I can read the variable, I
> won't be able to write to it. I still don't understand why not,
> though...


The real problem here is that you don't understand how python variables
work. And in fact, python does not have variables. It has names that
bind to objects. If you assign a value to a name, you're not
overwriting a variable, you're rebinding a name to a new object in the
default scope (unless it's declared global, or nonlocal in python 3, the
latter I assume uses the same scope in which it was first declared, but
I could be wrong). Since the name is in the local scope, the original
name in the caller's scope is still bound to its original object.

Furthermore, most primitive objects in python (strings, ints, etc) are
immutable, which means they can *never change*. "Writing" to a variable
simply dereferences the old object (which may still be referenced in the
caller's scope) and creates a new object and binds it to the name.

A list is mutable, which is why it's one solution to emulate a variable.

> As for python 3 ... "nonlocal"? I see I'm not alone in picking
> obnoxious names ...


nonlocal at least has meaning.
 
Reply With Quote
 
Mark Lawrence
Guest
Posts: n/a
 
      06-29-2013
On 29/06/2013 13:26, (E-Mail Removed) wrote:
> "PS: If you're reading this and love the French language -- I am deeply sorry
> for the pain I'm causing you..."
>
> It's obviously a team effort...
>
> My French ain't so hot, either. I had to google your "tout chez" until I ran into the explanation:
>
> hallo also ich gucke super gerne two and a half men und da wird öfters tout chez (keine ahnung ob es so geschrieben wird) gesagt. ich hab gegooglet aber nichts gefunden. ich habs auch überstzen lassen aber da kommt nur raus "alles bei"...das wirds ja wohl nicht sein^^ könnte mir also jemand sagen was es genau bedeutet wenn man das sagt?
>
> The answer for us TV-challenged non-views:
>
> Es heißt: "touché"
>


Try reading Stephen Clarke's "1000 Years of Annoying the French".
Perfect when summing up how good they are are at raising white flags
wherever and whenever it suits them.

--
"Steve is going for the pink ball - and for those of you who are
watching in black and white, the pink is next to the green." Snooker
commentator 'Whispering' Ted Lowe.

Mark Lawrence

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointers, pointers, pointers... cerr C Programming 12 04-07-2011 11:17 PM
Does deleting a container of pointers also delete the (contained) pointers? Xamalek C++ 7 11-04-2003 04:17 PM
c++: pointers to pointers A C++ 3 10-29-2003 01:15 PM
pointers to pointers // exception handling error muser C++ 3 09-18-2003 06:19 PM
Template specialization of pointers with function pointers Phil C++ 1 09-16-2003 02:17 AM



Advertisments