471,624 Members | 1,912 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

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

setting variables in outer functions

Given the following:
def outer(arg)
avar = ''
def inner1(arg2)
# How can I set 'avar' here ?

-------------------------------------
This sig is dedicated to the advancement of Nuclear Power
Tommy Nordgren
to************@comhem.se

Oct 29 '07 #1
18 2374
Tommy Nordgren wrote:
Given the following:
def outer(arg)
avar = ''
def inner1(arg2)
# How can I set 'avar' here ?
Try this... works for me... maybe not for you?

def outer(avar=False):
print avar
if avar == True:
return

def inner(avar=True):
print avar
return avar

outer(inner())

outer()
Oct 29 '07 #2
Tommy Nordgren <to************@comhem.sewrites:
Given the following:
def outer(arg)
avar = ''
def inner1(arg2)
# How can I set 'avar' here ?
I don't think you can, until Python 3:
http://www.python.org/dev/peps/pep-3104/

Currently the (ugly) solution is to change variable assignment to
object mutation:

def outer(arg)
avar = ['']
# use avar[0] where you'd normally use avar
def inner1(arg2)
# modify the value of avar by setting avar[0]
Oct 29 '07 #3

On 29 okt 2007, at 21.59, brad wrote:
Tommy Nordgren wrote:
>Given the following:
def outer(arg)
avar = ''
def inner1(arg2)
# How can I set 'avar' here ?

Try this... works for me... maybe not for you?

def outer(avar=False):
print avar
if avar == True:
return

def inner(avar=True):
print avar
return avar

outer(inner())

outer()
--
http://mail.python.org/mailman/listinfo/python-list
This is not a general solution to this problem.
What works, though, (I just thought of it) is to do the following:
def outer(arg):
adict = {}
def inner1(arg):
adict['avar'] = 'something'
#now the value set by inner1 is available to other nested functions
------
What is a woman that you forsake her, and the hearth fire and the
home acre,
to go with the old grey Widow Maker. --Kipling, harp song of the
Dane women
Tommy Nordgren
to************@comhem.se

Oct 29 '07 #4
Tommy Nordgren wrote:
>def outer(avar=False):
print avar
if avar == True:
return

def inner(avar=True):
print avar
return avar

outer(inner())

outer()
This is not a general solution to this problem.
Run my example code, it works (if I'm understanding your question
correctly). It sets outer to True... inner returns True to outer and
thus the var is set... am I missing something?
Oct 29 '07 #5
Hrvoje Niksic wrote:
Tommy Nordgren <to************@comhem.sewrites:
>Given the following:
def outer(arg)
avar = ''
def inner1(arg2)
# How can I set 'avar' here ?

I don't think you can, until Python 3:
http://www.python.org/dev/peps/pep-3104/
But it definitely does work in Python 3 if you use 'nonlocal'::

Python 3.0a1+ (py3k:58681, Oct 26 2007, 19:44:30) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more
information.
>>def f():
... x = 1
... def g():
... nonlocal x
... x = 2
... print(x)
... g()
... print(x)
...
>>f()
1
2

That said, I'd like to see the reason you think you want to do this.

STeVe
Oct 29 '07 #6
On 2007-10-29, Steven Bethard <st************@gmail.comwrote:
Hrvoje Niksic wrote:
>Tommy Nordgren <to************@comhem.sewrites:
>>Given the following:
def outer(arg)
avar = ''
def inner1(arg2)
# How can I set 'avar' here ?

I don't think you can, until Python 3:
http://www.python.org/dev/peps/pep-3104/

But it definitely does work in Python 3 if you use 'nonlocal'::

Python 3.0a1+ (py3k:58681, Oct 26 2007, 19:44:30) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more
information.
>>def f():
... x = 1
... def g():
... nonlocal x
... x = 2
... print(x)
... g()
... print(x)
...
>>f()
1
2

That said, I'd like to see the reason you think you want to do
this.
It's allows a standard programming idiom which provides a
primitive form of object oriented programming using closures to
represent state.

def account(opening_balance):
balance = opening_balance
def get_balance():
nonlocal balance
return balance
def post_transaction(x):
nonlocal balance
balance += x
return balance, post_transaction

fred_balance, fred_post = account(1500)
joe_balance, joe_post = account(12)
fred_post(20)
joe_post(-10)
fred_balance()
1520
joe_balance()
2

Python classes will of course nearly always win, though the idiom
looks like it might be faster (I don't have Python 3000 to try it
out).

--
Neil Cerutti
It isn't pollution that is hurting the environment; it's the impurities in our
air and water that are doing it. --Dan Quayle
Oct 30 '07 #7
Neil Cerutti wrote:
On 2007-10-29, Steven Bethard <st************@gmail.comwrote:
>Hrvoje Niksic wrote:
>>Tommy Nordgren <to************@comhem.sewrites:

Given the following:
def outer(arg)
avar = ''
def inner1(arg2)
# How can I set 'avar' here ?
I don't think you can, until Python 3:
http://www.python.org/dev/peps/pep-3104/
But it definitely does work in Python 3 if you use 'nonlocal'::

Python 3.0a1+ (py3k:58681, Oct 26 2007, 19:44:30) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more
information.
> >>def f():
... x = 1
... def g():
... nonlocal x
... x = 2
... print(x)
... g()
... print(x)
...
> >>f()
1
2

That said, I'd like to see the reason you think you want to do
this.

It's allows a standard programming idiom which provides a
primitive form of object oriented programming using closures to
represent state.
Yeah, that's what I was afraid of. ;-)

STeVe
Oct 30 '07 #8
Neil Cerutti <ho*****@yahoo.comwrote:
It's allows a standard programming idiom which provides a
primitive form of object oriented programming using closures to
represent state.

def account(opening_balance):
balance = opening_balance
def get_balance():
nonlocal balance
return balance
def post_transaction(x):
nonlocal balance
balance += x
return balance, post_transaction

fred_balance, fred_post = account(1500)
joe_balance, joe_post = account(12)
fred_post(20)
joe_post(-10)
fred_balance()
TypeError: 'int' object is not callable
1520
joe_balance()
TypeError: 'int' object is not callable
2

Python classes will of course nearly always win, though the idiom
looks like it might be faster (I don't have Python 3000 to try it
out).
Python classes might be less error prone. I expect they could also be
faster: accessing non-local variables (whether fetching or setting) has
always been suprisingly slow in Python 2.x.
Oct 30 '07 #9
brad a écrit :
Tommy Nordgren wrote:
>>def outer(avar=False):
print avar
if avar == True:
return

def inner(avar=True):
print avar
return avar

outer(inner())

outer()

> This is not a general solution to this problem.


Run my example code, it works (if I'm understanding your question
correctly). It sets outer to True... inner returns True to outer and
thus the var is set... am I missing something?
Yes: you forgot to rebind avar in inner and check the result in outer.
Oct 30 '07 #10
On Oct 30, 11:29 am, Duncan Booth <duncan.bo...@invalid.invalid>
wrote:
Neil Cerutti <horp...@yahoo.comwrote:
It's allows a standard programming idiom which provides a
primitive form of object oriented programming using closures to
represent state.
def account(opening_balance):
balance = opening_balance
def get_balance():
nonlocal balance
return balance
def post_transaction(x):
nonlocal balance
balance += x
return balance, post_transaction
fred_balance, fred_post = account(1500)
joe_balance, joe_post = account(12)
fred_post(20)
joe_post(-10)
fred_balance()

TypeError: 'int' object is not callable
1520
joe_balance()

TypeError: 'int' object is not callable
2
Python classes will of course nearly always win, though the idiom
looks like it might be faster (I don't have Python 3000 to try it
out).

Python classes might be less error prone.
Why would using classes make your code any less prone to typographical
errors?

Oct 31 '07 #11
Dustan <Du**********@gmail.comwrote:
On Oct 30, 11:29 am, Duncan Booth <duncan.bo...@invalid.invalid>
wrote:
>Neil Cerutti <horp...@yahoo.comwrote:
It's allows a standard programming idiom which provides a
primitive form of object oriented programming using closures to
represent state.
def account(opening_balance):
balance = opening_balance
def get_balance():
nonlocal balance
return balance
def post_transaction(x):
nonlocal balance
balance += x
return balance, post_transaction
fred_balance, fred_post = account(1500)
joe_balance, joe_post = account(12)
fred_post(20)
joe_post(-10)
fred_balance()

TypeError: 'int' object is not callable
1520
joe_balance()

TypeError: 'int' object is not callable
2
Python classes will of course nearly always win, though the idiom
looks like it might be faster (I don't have Python 3000 to try it
out).

Python classes might be less error prone.

Why would using classes make your code any less prone to typographical
errors?

Lots of reasons: shorter and clearer code being high on the list. The
class equivalent would be:

>>class Account(object):
def __init__(self, opening_balance):
self.balance = opening_balance

def post_transaction(self, x):
self.balance += x

>>fred = Account(1500)
joe = Account(12)
fred.post_transaction(20)
joe.post_transaction(-10)
fred.balance
1520
>>joe.balance
2

There is no scope for the particular error I highlighted: you no longer
have the duplication of declaring the functions and then returning them.
Also you don't need the accessor function at all (and if at some point
in the future you do want it you can make it a property).

You don't have to invent separate names for each of the returned
functions: the dot notation suddenly makes that a no brainer.

Also the class is easier to extend: you no longer have to find and
change every call to account() if you want to add another method: just
add it.

BTW, I put both the original code with corrections, and the class
version into a file and timed them running with Python 3 alpha 1, the
nested scope version is slightly faster: 5.03usec per loop against
5.77usec for the class version, but minor changes to the code can skew
the result either way (put in more attribute accesses and the class
wins, add in more method calls and the function wins).
Oct 31 '07 #12
On Oct 31, 7:08 am, Duncan Booth <duncan.bo...@invalid.invalidwrote:
Dustan <DustanGro...@gmail.comwrote:
On Oct 30, 11:29 am, Duncan Booth <duncan.bo...@invalid.invalid>
wrote:
Neil Cerutti <horp...@yahoo.comwrote:
It's allows a standard programming idiom which provides a
primitive form of object oriented programming using closures to
represent state.
def account(opening_balance):
balance = opening_balance
def get_balance():
nonlocal balance
return balance
def post_transaction(x):
nonlocal balance
balance += x
return balance, post_transaction
fred_balance, fred_post = account(1500)
joe_balance, joe_post = account(12)
fred_post(20)
joe_post(-10)
fred_balance()
TypeError: 'int' object is not callable
1520
joe_balance()
TypeError: 'int' object is not callable
2
Python classes will of course nearly always win, though the idiom
looks like it might be faster (I don't have Python 3000 to try it
out).
Python classes might be less error prone.
Why would using classes make your code any less prone to typographical
errors?

Lots of reasons: shorter and clearer code being high on the list.
It wouldn't be necessarily shorter, depending on what you're working
with. Clearer is a matter of opinion.
The
class equivalent would be:
>class Account(object):

def __init__(self, opening_balance):
self.balance = opening_balance

def post_transaction(self, x):
self.balance += x
>fred = Account(1500)
joe = Account(12)
fred.post_transaction(20)
joe.post_transaction(-10)
fred.balance
1520
>joe.balance

2

There is no scope for the particular error I highlighted: you no longer
have the duplication of declaring the functions and then returning them.
The 'particular error' you highlighted was a typographical error,
which can happen in any code. Sure, you can't have the exact same
typographical error, but that's what happens when you switch between
paradigms.
Also you don't need the accessor function at all (and if at some point
in the future you do want it you can make it a property).

You don't have to invent separate names for each of the returned
functions: the dot notation suddenly makes that a no brainer.
Fair enough; you got two valid arguments there.
Also the class is easier to extend: you no longer have to find and
change every call to account() if you want to add another method: just
add it.
Of course, there are cases where you'll never want to extend it.

Oct 31 '07 #13
On Oct 31, 2007 5:49 PM, Dustan <Du**********@gmail.comwrote:
On Oct 31, 7:08 am, Duncan Booth <duncan.bo...@invalid.invalidwrote:
Dustan <DustanGro...@gmail.comwrote:
On Oct 30, 11:29 am, Duncan Booth <duncan.bo...@invalid.invalid>
wrote:
>Neil Cerutti <horp...@yahoo.comwrote:
It's allows a standard programming idiom which provides a
primitive form of object oriented programming using closures to
represent state.
def account(opening_balance):
balance = opening_balance
def get_balance():
nonlocal balance
return balance
def post_transaction(x):
nonlocal balance
balance += x
return balance, post_transaction
fred_balance, fred_post = account(1500)
joe_balance, joe_post = account(12)
fred_post(20)
joe_post(-10)
fred_balance()
>TypeError: 'int' object is not callable
1520
joe_balance()
>TypeError: 'int' object is not callable
2
Python classes will of course nearly always win, though the idiom
looks like it might be faster (I don't have Python 3000 to try it
out).
>Python classes might be less error prone.
Why would using classes make your code any less prone to typographical
errors?
Lots of reasons: shorter and clearer code being high on the list.

It wouldn't be necessarily shorter, depending on what you're working
with. Clearer is a matter of opinion.
It's going to be shorter in any non-trivial example, and even in most
trivial ones (as shown). Clearer may be a matter of opinion, but the
less complicated the code you're looking at is, the less chance you
have to make an error.
The
class equivalent would be:
>>class Account(object):
def __init__(self, opening_balance):
self.balance = opening_balance

def post_transaction(self, x):
self.balance += x
>>fred = Account(1500)
>>joe = Account(12)
>>fred.post_transaction(20)
>>joe.post_transaction(-10)
>>fred.balance
1520
>>joe.balance
2

There is no scope for the particular error I highlighted: you no longer
have the duplication of declaring the functions and then returning them.

The 'particular error' you highlighted was a typographical error,
which can happen in any code. Sure, you can't have the exact same
typographical error, but that's what happens when you switch between
paradigms.
By having fewer explicit things to manage, you lessen the scope of
errors in naming those things. This is one reason why the DRY
principle is advocated - the fewer times you type something, the fewer
chances you have to typo it.
Also you don't need the accessor function at all (and if at some point
in the future you do want it you can make it a property).

You don't have to invent separate names for each of the returned
functions: the dot notation suddenly makes that a no brainer.

Fair enough; you got two valid arguments there.
Also the class is easier to extend: you no longer have to find and
change every call to account() if you want to add another method: just
add it.

Of course, there are cases where you'll never want to extend it.
Designing it in such a way that it's impossible to extend pretty much
ensures that, doesn't it?

I have no idea why someone who already has a working, object system
would want to implement their own on top of closures. I'd even take
issue with the idea that's it's a "standard" idiom for the quite
uncommon task of creating object systems, it's a well known conceptual
idea but it's not actually implemented as such very often.
Oct 31 '07 #14
"Chris Mellon" <ar*****@gmail.comwrites:
I have no idea why someone who already has a working, object system
would want to implement their own on top of closures.
This subthread is getting ridiculous -- closures are *not* useful only
for implementing object systems! The object system thing is just a
method of teaching abstractions popularized by SICP. Abstractions
normally taken for granted, such as objects, or even expression
evaluation, are implemented from scratch, using only the most basic
primitives available. In a Lisp-like language with lexical scope, the
most basic storage primitive is the lexical environment itself[1].

In real-life code, closures are used to implement callbacks with
automatic access to their lexical environment without the need for the
bogus additional "void *" argument one so often sees in C callbacks,
and without communication through global variables. If the callbacks
can access variables in the outer scope, it's only logical (and
useful) for them to be able to change them. Prohibiting modification
reduces the usefulness of closures and causes ugly workarounds such as
the avar[0] pattern.

If closures were useful only for implementing bogus object systems,
neither they nor "nonlocal" would have made it to Python in the first
place.
[1]
An illustration of that principle is an implementation of cons, the
most primitive Lisp storage type, without the use of a higher-level
storage object (such as a two-element vector):

(defun cons (x y)
(lambda (op)
(if op x y)))
(defun car (cons) (funcall cons t))
(defun cdr (cons) (funcall cons nil))
Oct 31 '07 #15
Hrvoje Niksic schrieb:
"Chris Mellon" <ar*****@gmail.comwrites:
>I have no idea why someone who already has a working, object system
would want to implement their own on top of closures.

This subthread is getting ridiculous -- closures are *not* useful only
for implementing object systems! The object system thing is just a
method of teaching abstractions popularized by SICP. Abstractions
normally taken for granted, such as objects, or even expression
evaluation, are implemented from scratch, using only the most basic
primitives available. In a Lisp-like language with lexical scope, the
most basic storage primitive is the lexical environment itself[1].

In real-life code, closures are used to implement callbacks with
automatic access to their lexical environment without the need for the
bogus additional "void *" argument one so often sees in C callbacks,
and without communication through global variables. If the callbacks
can access variables in the outer scope, it's only logical (and
useful) for them to be able to change them. Prohibiting modification
reduces the usefulness of closures and causes ugly workarounds such as
the avar[0] pattern.

If closures were useful only for implementing bogus object systems,
neither they nor "nonlocal" would have made it to Python in the first
place.
There's a nice saying about this:

"""
The venerable master Qc Na was walking with his student, Anton.
Hoping to
prompt the master into a discussion, Anton said "Master, I have heard that
objects are a very good thing - is this true?" Qc Na looked pityingly at
his student and replied, "Foolish pupil - objects are merely a poor man's
closures."

Chastised, Anton took his leave from his master and returned to his cell,
intent on studying closures. He carefully read the entire "Lambda: The
Ultimate..." series of papers and its cousins, and implemented a small
Scheme interpreter with a closure-based object system. He learned much, and
looked forward to informing his master of his progress.

On his next walk with Qc Na, Anton attempted to impress his master by
saying "Master, I have diligently studied the matter, and now understand
that objects are truly a poor man's closures." Qc Na responded by hitting
Anton with his stick, saying "When will you learn? Closures are a poor man's
object." At that moment, Anton became enlightened.
"""

http://people.csail.mit.edu/gregs/ll.../msg03277.html
I do love closures, and I sometimes pitty python for not allowing to set
outer scope variables.

But then, it's because it lacks a variable declaration scheme (as e.g.
javascript has), so _some_ design decision had to be made distinguishing
variable declarations from pure references. And I can live with the
consequences.

Diez
Nov 1 '07 #16
Hrvoje Niksic <hn*****@xemacs.orgwrote:
In real-life code, closures are used to implement callbacks with
automatic access to their lexical environment without the need for the
bogus additional "void *" argument one so often sees in C callbacks,
and without communication through global variables. If the callbacks
can access variables in the outer scope, it's only logical (and
useful) for them to be able to change them. Prohibiting modification
reduces the usefulness of closures and causes ugly workarounds such as
the avar[0] pattern.
In real life code methods are used to implement callbacks with automatic
access to their environment without the need for any C type hacks.

What is your point here? Python isn't C (or Javascript). If you have a
function which takes a callback in Python you just pass it a bound method
and you have all the context you want without resorting to ugly workrounds.
Nov 1 '07 #17
On Oct 31, 5:59 pm, "Chris Mellon" <arka...@gmail.comwrote:
On Oct 31, 2007 5:49 PM, Dustan <DustanGro...@gmail.comwrote:
[snip]

I'm not going to respond to any of this, but I'm just going to say:
I'm not claiming that the use of closures is common. I'm just claiming
that it can be useful. I have used closures exactly once. I feel that
that one time, it was for a good cause.

Nov 1 '07 #18
Hrvoje Niksic a écrit :
"Chris Mellon" <ar*****@gmail.comwrites:

>>I have no idea why someone who already has a working, object system
would want to implement their own on top of closures.


This subthread is getting ridiculous -- closures are *not* useful only
for implementing object systems! The object system thing is just a
method of teaching abstractions popularized by SICP. Abstractions
normally taken for granted, such as objects, or even expression
evaluation, are implemented from scratch, using only the most basic
primitives available. In a Lisp-like language with lexical scope, the
most basic storage primitive is the lexical environment itself[1].

In real-life code, closures are used to implement callbacks with
automatic access to their lexical environment without the need for the
bogus additional "void *" argument one so often sees in C callbacks,
and without communication through global variables. If the callbacks
can access variables in the outer scope, it's only logical (and
useful) for them to be able to change them. Prohibiting modification
reduces the usefulness of closures and causes ugly workarounds such as
the avar[0] pattern.

If closures were useful only for implementing bogus object systems,
neither they nor "nonlocal" would have made it to Python in the first
place.
Indeed. But please read carefully the classic piece of wisdom quoted by
Diez in his answer. Then remember that in Python, callable objects
doesn't need to be functions, and most of what can be done (and is
usually done in FPLs) can be done with objects. Look at the sample
Python implementation of partial evaluation, or at all the so-called
decorators that are not functions but really classes.

I do use Python's closures quite a lot myself, because it's often
simpler than doing it the OO way. But for whatever slightly more
involved, I prefer to write my own classes, and I'll still do so if and
when Python grows "full-blown" closures.
Nov 4 '07 #19

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by erica | last post: by
1 post views Thread by Etienne Fortin | last post: by
18 posts views Thread by noridotjabi | last post: by
3 posts views Thread by zero.maximum | last post: by
41 posts views Thread by Jim | last post: by
4 posts views Thread by Eric Lilja | last post: by
2 posts views Thread by Licheng Fang | last post: by
9 posts views Thread by Matthias Buelow | last post: by
1 post views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by

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.