By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,795 Members | 1,216 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,795 IT Pros & Developers. It's quick & easy.

Nested function scope problem

P: n/a
I found that I was repeating the same couple of lines over and over in
a function and decided to split those lines into a nested function
after copying one too many minor changes all over. The only problem is
that my little helper function doesn't work! It claims that a variable
doesn't exist. If I move the variable declaration, it finds the
variable, but can't change it. Declaring the variable global in the
nested function doesn't work either.

But, changing the variable in the containing scope is the whole purpose
of this helper function.

I'm new to python, so there is probably some solution I haven't
encountered yet. Could you please suggest a nice clean solution? The
offending code is below. Thanks.

def breakLine(s):
"""Break a string into a list of words and symbols.
"""
def addTok():
if len(tok) 0:
ls.append(tok)
tok = ''

ls = []
tok = ''
splitters = '?()&|:~,'
whitespace = ' \t\n\r'

for c in s:
if c in splitters:
addTok()
ls.append(c)
elif c in whitespace:
addTok()
else:
tok = tok + c

addTok()

return ls

#some tests to make sure it works
print breakLine('carolina(Prada):cat(X,Y)')
print breakLine('trouble :bird (X ) &cat ( Y )')
print breakLine('?trouble')

Jul 22 '06 #1
Share this Question
Share on Google+
78 Replies


P: n/a
On 2006-07-21 21:05:22, Josiah Manson wrote:
I found that I was repeating the same couple of lines over and over in
a function and decided to split those lines into a nested function
after copying one too many minor changes all over. The only problem is
that my little helper function doesn't work! It claims that a variable
doesn't exist. If I move the variable declaration, it finds the
variable, but can't change it. Declaring the variable global in the
nested function doesn't work either.

But, changing the variable in the containing scope is the whole purpose
of this helper function.

I'm new to python, so there is probably some solution I haven't
encountered yet. Could you please suggest a nice clean solution? The
offending code is below. Thanks.
I'm no Python specialist, so here's just some guesses... I don't know how
to make variables known inside the inner function. It seems just using the
names there overrides the outside names. It also seems that local variables
are in some kind of dictionary; so maybe you can access them through that
somehow.

One other solution (a bit ugly) would be to make this a class with two
static methods (breakLine and _addTok) and two static attributes (_ls and
_tok).

Still another (also ugly) would be to pass both tok and ls to addTok() and
pass tok back out again. (I think ls doesn't have to be passed back,
because it is a list and so its data gets modified. tok's data doesn't get
modified, so local changes don't propagate to the outside.)

Gerhard

Jul 22 '06 #2

P: n/a
Gerhard Fiedler wrote:
On 2006-07-21 21:05:22, Josiah Manson wrote:
I found that I was repeating the same couple of lines over and over in
a function and decided to split those lines into a nested function
after copying one too many minor changes all over. The only problem is
that my little helper function doesn't work! It claims that a variable
doesn't exist. If I move the variable declaration, it finds the
variable, but can't change it. Declaring the variable global in the
nested function doesn't work either.

But, changing the variable in the containing scope is the whole purpose
of this helper function.

I'm new to python, so there is probably some solution I haven't
encountered yet. Could you please suggest a nice clean solution? The
offending code is below. Thanks.

I'm no Python specialist, so here's just some guesses... I don't know how
to make variables known inside the inner function. It seems just using the
names there overrides the outside names. It also seems that local variables
are in some kind of dictionary; so maybe you can access them through that
somehow.

One other solution (a bit ugly) would be to make this a class with two
static methods (breakLine and _addTok) and two static attributes (_ls and
_tok).

Still another (also ugly) would be to pass both tok and ls to addTok() and
pass tok back out again. (I think ls doesn't have to be passed back,
because it is a list and so its data gets modified. tok's data doesn't get
modified, so local changes don't propagate to the outside.)

Gerhard
That third option seems to work fine.

def breakLine(s):
"""Break a string into a list of words and symbols.
"""

def addTok(tok, ls):
if len(tok) 0:
ls.append(tok)
tok = ''
return tok

ls = []
tok = ''
splitters = '?()&|:~,'
whitespace = ' \t\n\r'

for c in s:
if c in splitters:
tok = addTok(tok, ls)
ls.append(c)
elif c in whitespace:
tok = addTok(tok, ls)
else:
tok = tok + c

tok = addTok(tok, ls)

return ls

#some tests to make sure it works
print breakLine('carolina(Prada):cat(X,Y)')
print breakLine('trouble :bird (X ) &cat ( Y )')
print breakLine('?trouble')

# Prints:
['carolina', '(', 'Prada', ')', ':', 'cat', '(', 'X', ',', 'Y', ')']
['trouble', ':', 'bird', '(', 'X', ')', '&', 'cat', '(', 'Y', ')']
['?', 'trouble']

Jul 22 '06 #3

P: n/a
Simon Forman wrote:
That third option seems to work fine.
Well it does, but there are still many things wrong with it

if len(tok) 0:
should be written as
if(tok):

tok = ''
tok = toc + c
should be written as
tok = []
tok.append(c)
and later
''.join(toc)

anyway, the entire thing should be replaced with something like this:
import re
def breakLine(s):
splitters = '?()&|:~,'
chars = '^ \t\n\r\f\v%s' % splitters
regex = '''(
(?:[%s])
|
(?:[%s]+))''' % (splitters, chars)
return re.findall(regex, s,re.VERBOSE)

That should be able to be simplified even more if one were to use the
character lists built into the regex standard.

--
- Justin

Jul 22 '06 #4

P: n/a
In message <11**********************@m79g2000cwm.googlegroups .com>, Justin
Azoff wrote:
Simon Forman wrote:
>That third option seems to work fine.

Well it does, but there are still many things wrong with it

if len(tok) 0:
should be written as
if(tok):
I prefer the first way. Besides, your way is sub-optimal.
Jul 22 '06 #5

P: n/a
Thank you for your corrections to the previous code. Your regex
solution is definitely much cleaner. Referring to your other
suggestions, is the advantage of using a list of chars instead of
adding to a string just a bow to big-O complexity, or are there other
considerations? First I had tried appending to the string, but it seems
they are immutable. It seems that using a list for a string isn't a
very clear way to represent a mutable string.

Although I gladly accept that using a regex is the best solution to
this problem, I am still interested in knowing how to access the
variables in a containing function. It seems that there should be some
keyword akin to global that would expose them, or some other method. I
have read that python uses nested scopes (or at least was planning to
in 2.2), so I wonder what I am missing.

Jul 22 '06 #6

P: n/a
I just did some timings, and found that using a list instead of a
string for tok is significantly slower (it takes 1.5x longer). Using a
regex is slightly faster for long strings, and slightly slower for
short ones. So, regex wins in both berevity and speed!

Jul 22 '06 #7

P: n/a
Josiah Manson wrote:
I just did some timings, and found that using a list instead of a
string for tok is significantly slower (it takes 1.5x longer). Using a
regex is slightly faster for long strings, and slightly slower for
short ones. So, regex wins in both berevity and speed!
I think the list.append method of building strings may only give you
speed improvements when you are adding bigger chunks of strings
together instead of 1 character at a time. also:

http://docs.python.org/whatsnew/node...00000000000000

"""String concatenations in statements of the form s = s + "abc" and s
+= "abc" are now performed more efficiently in certain circumstances.
This optimization won't be present in other Python implementations such
as Jython, so you shouldn't rely on it; using the join() method of
strings is still recommended when you want to efficiently glue a large
number of strings together. (Contributed by Armin Rigo.)"""

I tested both, and these are my results for fairly large strings:

justin@latitude:/tmp$ python /usr/lib/python2.4/timeit.py -s'import
foo' 'foo.test(foo.breakLine)'
10 loops, best of 3: 914 msec per loop

justin@latitude:/tmp$ python /usr/lib/python2.4/timeit.py -s'import
foo' 'foo.test(foo.breakLineRE)'
10 loops, best of 3: 289 msec per loop

--
- Justin

Jul 22 '06 #8

P: n/a
Josiah Manson a écrit :
I found that I was repeating the same couple of lines over and over in
a function and decided to split those lines into a nested function
after copying one too many minor changes all over. The only problem is
that my little helper function doesn't work! It claims that a variable
doesn't exist. If I move the variable declaration, it finds the
variable, but can't change it. Declaring the variable global in the
nested function doesn't work either.

But, changing the variable in the containing scope is the whole purpose
of this helper function.

I'm new to python, so there is probably some solution I haven't
encountered yet. Could you please suggest a nice clean solution? The
offending code is below. Thanks.

def breakLine(s):
"""Break a string into a list of words and symbols.
"""
def addTok():
if len(tok) 0:
if tok:

An empty sequence evals to False in a boolean context.
ls.append(tok)
tok = ''
First point: the nested function only have access to names that exists
in the enclosing namespace at the time it's defined.

Second point: a nested function cannot rebind names from the enclosing
namespace. Note that in Python, rebinding a name and modifying the
object bound to a name are very distinct operations.

Third point : functions modifying their environment this way are usually
considered bad form.

Here's a possible solution - but note that there are probably much
better ways to get the same result...

def breakline(line):
"""Break a string into a list of words and symbols."""
class TokenList(list):
def append(self, token):
if token:
list.append(self, token)
return ''

tokens = TokenList()
token = ''
splitters = '?()&|:~,'
whitespace = ' \t\n\r'
specials = splitters + whitespace

for char in line:
if char in specials:
token = tokens.append(token)
if char in splitters:
tokens.append(char)
else:
token += char

tokens.append(token)
return list(tokens)

(snip)
Jul 22 '06 #9

P: n/a
Justin Azoff a écrit :
Simon Forman wrote:
>>That third option seems to work fine.


Well it does, but there are still many things wrong with it
(snip)
tok = ''
tok = toc + c
should be written as
tok = []
tok.append(c)
and later
''.join(toc)
IIRC, string concatenation slowness has been fixed a few versions ago -
at least in CPython - , so there's no more reason to use this idiom.

(snip)
Jul 22 '06 #10

P: n/a
Justin Azoff a écrit :
Simon Forman wrote:
>>That third option seems to work fine.


Well it does, but there are still many things wrong with it

if len(tok) 0:
should be written as
if(tok):
actually, the parenthesis are useless.
Jul 22 '06 #11

P: n/a
Lawrence D'Oliveiro a écrit :
In message <11**********************@m79g2000cwm.googlegroups .com>, Justin
Azoff wrote:

>>Simon Forman wrote:
>>>That third option seems to work fine.

Well it does, but there are still many things wrong with it

if len(tok) 0:
should be written as
if(tok):


I prefer the first way.
This is your right, but it's not the python idiom.
Besides, your way is sub-optimal.
Care to explain ?
Jul 22 '06 #12

P: n/a
Bruno Desthuilliers wrote:
Justin Azoff a écrit :
if len(tok) 0:
should be written as
if(tok):

actually, the parenthesis are useless.
yes, that's what happens when you edit something instead of typing it
over from scratch :-)

--
- Justin

Jul 22 '06 #13

P: n/a
Bruno Desthuilliers wrote:
Josiah Manson a écrit :
I found that I was repeating the same couple of lines over and over in
a function and decided to split those lines into a nested function
after copying one too many minor changes all over. The only problem is
that my little helper function doesn't work! It claims that a variable
doesn't exist. If I move the variable declaration, it finds the
variable, but can't change it. Declaring the variable global in the
nested function doesn't work either.

But, changing the variable in the containing scope is the whole purpose
of this helper function.

I'm new to python, so there is probably some solution I haven't
encountered yet. Could you please suggest a nice clean solution? The
offending code is below. Thanks.

def breakLine(s):
"""Break a string into a list of words and symbols.
"""
def addTok():
if len(tok) 0:

if tok:

An empty sequence evals to False in a boolean context.
ls.append(tok)
tok = ''
I can't figure out why Josiah's breakLine function won't work either. I
know Josiah has had his problem resolved, but I'd still like to know
why his func won't work. I'd like to redirect this discussion in that
direction, if I may.
>
First point: the nested function only have access to names that exists
in the enclosing namespace at the time it's defined.
Coming from lisp, that doesn't make very much sense, and I'm not sure
that's true. If you move the def for addTok bellow the lines that
initialize the locals of breakLines, you still get the same problem.
>
Second point: a nested function cannot rebind names from the enclosing
namespace. Note that in Python, rebinding a name and modifying the
object bound to a name are very distinct operations.
I'm not sure that's the problem, because when I ran the debugger, the
problem is with the line that says if len(tok), not the one bellow it
which says tok = "". Regardless, my above issue seems to be overriding
this one.
>
Third point : functions modifying their environment this way are usually
considered bad form.
Again, this is coming from lisp, but I don't see anything wrong with
that :P.

***

After some experimentation, I am completely baffeled as to why
breakLine won't work. Here is an example of one of the things I did,
which I believe exactly mimics what breakLine does:
>>def outer():
.... def inner():
.... if outerLocal:
.... return "I hear you, 'hello world'."
.... else:
.... return "Come again?"
.... outerLocal = "hello world"
.... return inner()
....
>>outer()
"I hear you, 'hello world'."

As I said, I believe the line which sets tok should break (quietly),
but not the line which tests tok. My experiment seems to confirm
this...

One thing I can understand is why the line tok = "" in addTok won't
work. This is because when Python sees that line, it should create a
new local variable in the scope of addTok. Once addTok returns, that
variable is lost. That's pretty deep, now that I've thought about it...
>
Here's a possible solution - but note that there are probably much
better ways to get the same result...

def breakline(line):
"""Break a string into a list of words and symbols."""
class TokenList(list):
def append(self, token):
if token:
list.append(self, token)
return ''

tokens = TokenList()
token = ''
splitters = '?()&|:~,'
whitespace = ' \t\n\r'
specials = splitters + whitespace

for char in line:
if char in specials:
token = tokens.append(token)
if char in splitters:
tokens.append(char)
else:
token += char

tokens.append(token)
return list(tokens)

(snip)
Jul 23 '06 #14

P: n/a
On 2006-07-23 14:53:33, danielx wrote:
I can't figure out why Josiah's breakLine function won't work either. I
know Josiah has had his problem resolved, but I'd still like to know
why his func won't work. I'd like to redirect this discussion in that
direction, if I may.
I think what happens is this (and this may not be expressed in the proper
terms for Python): It is possible to read variables from the outer function
in the inner function. But when trying to write to them, this causes that
same name to be re-defined in the inner function's scope, making it a
different variable. Now, in the OP's code, that caused that new variable
(with scope of the inner function) to be accessed before anything was
assigned to it.

One obvious way is to not write to the variables from the outer scope, but
rather return a value from the inner function and assign it in the outer
function. But it seems there should be a way to be able to write in the
inner function to variables that are defined in the outer function.

>First point: the nested function only have access to names that exists
in the enclosing namespace at the time it's defined.

Coming from lisp, that doesn't make very much sense, and I'm not sure
that's true. If you move the def for addTok bellow the lines that
initialize the locals of breakLines, you still get the same problem.
The problem there is only secondarily a scope problem. At first it is
reading a variable (the inner function scope variable tok) before anything
has been assigned to it. Of course, the real problem is the secondary one:
that this variable tok is a variable of scope addTok and not of scope
breakLine.
>Second point: a nested function cannot rebind names from the enclosing
namespace. Note that in Python, rebinding a name and modifying the
object bound to a name are very distinct operations.

I'm not sure that's the problem, because when I ran the debugger, the
problem is with the line that says if len(tok), not the one bellow it
which says tok = "". Regardless, my above issue seems to be overriding
this one.
Yes, but it is the line "tok = ''" that seems to cause tok to be now a
variable of the inner function's scope (rather than the variable tok of
breakLine).

After some experimentation, I am completely baffeled as to why
breakLine won't work. Here is an example of one of the things I did,
which I believe exactly mimics what breakLine does:
>>>def outer():
... def inner():
... if outerLocal:
... return "I hear you, 'hello world'."
... else:
... return "Come again?"
... outerLocal = "hello world"
... return inner()
...
>>>outer()
"I hear you, 'hello world'."

As I said, I believe the line which sets tok should break (quietly),
but not the line which tests tok. My experiment seems to confirm
this...
The line that sets tok causes tok to be a different tok from the outer tok
-- in the whole scope of the assignment.

Gerhard

Jul 23 '06 #15

P: n/a
Bruno Desthuilliers wrote:
(snip)
First point: the nested function only have access to names that exists
in the enclosing namespace at the time it's defined.
Duh.

Sometimes I'd better go to bed instead of answering posts here - I'd say
less stupidities. re-reading this, I can't believe I actually wrote such
an absurdity.


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 24 '06 #16

P: n/a
danielx wrote:
Bruno Desthuilliers wrote:
>>Josiah Manson a écrit :
>>>I found that I was repeating the same couple of lines over and over in
a function and decided to split those lines into a nested function
after copying one too many minor changes all over. The only problem is
that my little helper function doesn't work! It claims that a variable
doesn't exist. If I move the variable declaration, it finds the
variable, but can't change it. Declaring the variable global in the
nested function doesn't work either.

But, changing the variable in the containing scope is the whole purpose
of this helper function.

I'm new to python, so there is probably some solution I haven't
encountered yet. Could you please suggest a nice clean solution? The
offending code is below. Thanks.

def breakLine(s):
"""Break a string into a list of words and symbols.
"""
def addTok():
if len(tok) 0:

if tok:

An empty sequence evals to False in a boolean context.

>>> ls.append(tok)
tok = ''


I can't figure out why Josiah's breakLine function won't work either. I
know Josiah has had his problem resolved, but I'd still like to know
why his func won't work. I'd like to redirect this discussion in that
direction, if I may.

>>First point: the nested function only have access to names that exists
in the enclosing namespace at the time it's defined.
oops - Sorry, said an obvious stupidity here (was very tired, should not
have answered at all...)
>
Coming from lisp, that doesn't make very much sense, and I'm not sure
that's true. If you move the def for addTok bellow the lines that
initialize the locals of breakLines, you still get the same problem.
of course.
>
>>Second point: a nested function cannot rebind names from the enclosing
namespace. Note that in Python, rebinding a name and modifying the
object bound to a name are very distinct operations.


I'm not sure that's the problem, because when I ran the debugger, the
problem is with the line that says if len(tok), not the one bellow it
which says tok = "".
That's a side-effect of rebinding tok - it makes the name local. Even if
the rebiding is done *after* first use of the name...

>
>>Third point : functions modifying their environment this way are usually
considered bad form.


Again, this is coming from lisp, but I don't see anything wrong with
that :P.

***

After some experimentation, I am completely baffeled as to why
breakLine won't work. Here is an example of one of the things I did,
which I believe exactly mimics what breakLine does:
>>>>def outer():

... def inner():
... if outerLocal:
... return "I hear you, 'hello world'."
... else:
... return "Come again?"
... outerLocal = "hello world"
... return inner()
...
>>>>outer()

"I hear you, 'hello world'."

As I said, I believe the line which sets tok should break (quietly),
but not the line which tests tok. My experiment seems to confirm
this...
You did not rebind 'outerLocal' in your above code.
One thing I can understand is why the line tok = "" in addTok won't
work. This is because when Python sees that line, it should create a
new local variable in the scope of addTok.
Yes. But this local name is referenced before assignment.
Once addTok returns, that
variable is lost. That's pretty deep, now that I've thought about it...
(snip)

Sorry once again for the obvious stupidity I wrote as first point. Next
time I'll go to bed instead, I promise :(

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 24 '06 #17

P: n/a
Gerhard Fiedler wrote:
On 2006-07-23 14:53:33, danielx wrote:
I can't figure out why Josiah's breakLine function won't work either. I
know Josiah has had his problem resolved, but I'd still like to know
why his func won't work. I'd like to redirect this discussion in that
direction, if I may.

I think what happens is this (and this may not be expressed in the proper
terms for Python): It is possible to read variables from the outer function
in the inner function. But when trying to write to them, this causes that
same name to be re-defined in the inner function's scope, making it a
different variable. Now, in the OP's code, that caused that new variable
(with scope of the inner function) to be accessed before anything was
assigned to it.

One obvious way is to not write to the variables from the outer scope, but
rather return a value from the inner function and assign it in the outer
function. But it seems there should be a way to be able to write in the
inner function to variables that are defined in the outer function.

First point: the nested function only have access to names that exists
in the enclosing namespace at the time it's defined.
Coming from lisp, that doesn't make very much sense, and I'm not sure
that's true. If you move the def for addTok bellow the lines that
initialize the locals of breakLines, you still get the same problem.

The problem there is only secondarily a scope problem. At first it is
reading a variable (the inner function scope variable tok) before anything
has been assigned to it. Of course, the real problem is the secondary one:
that this variable tok is a variable of scope addTok and not of scope
breakLine.
Second point: a nested function cannot rebind names from the enclosing
namespace. Note that in Python, rebinding a name and modifying the
object bound to a name are very distinct operations.
I'm not sure that's the problem, because when I ran the debugger, the
problem is with the line that says if len(tok), not the one bellow it
which says tok = "". Regardless, my above issue seems to be overriding
this one.

Yes, but it is the line "tok = ''" that seems to cause tok to be now a
variable of the inner function's scope (rather than the variable tok of
breakLine).
OHH! Yes, that sounds like it could be it. Wow, to me, that behavior is
eXtremely unexpected (there's lisp popping up its ugly head again :P).
So you're saying that because an assignment to tok appears later within
the def for addTok, that the line if len(tok) won't try to look in
enclosing local scopes? (If such things even exist...)

Gerhard's reply sounded not so confident. Can we have someone who
"really" knows weigh in on this? Thanks!
>
After some experimentation, I am completely baffeled as to why
breakLine won't work. Here is an example of one of the things I did,
which I believe exactly mimics what breakLine does:
>>def outer():
... def inner():
... if outerLocal:
... return "I hear you, 'hello world'."
... else:
... return "Come again?"
... outerLocal = "hello world"
... return inner()
...
>>outer()
"I hear you, 'hello world'."

As I said, I believe the line which sets tok should break (quietly),
but not the line which tests tok. My experiment seems to confirm
this...

The line that sets tok causes tok to be a different tok from the outer tok
-- in the whole scope of the assignment.

Gerhard
Jul 24 '06 #18

P: n/a
danielx wrote:
Gerhard Fiedler wrote:
[...]
>>Yes, but it is the line "tok = ''" that seems to cause tok to be now a
variable of the inner function's scope (rather than the variable tok of
breakLine).


OHH! Yes, that sounds like it could be it. Wow, to me, that behavior is
eXtremely unexpected (there's lisp popping up its ugly head again :P).
So you're saying that because an assignment to tok appears later within
the def for addTok, that the line if len(tok) won't try to look in
enclosing local scopes? (If such things even exist...)

Gerhard's reply sounded not so confident. Can we have someone who
"really" knows weigh in on this? Thanks!
Would I do? If there's a binding to a name *anywhere* in the function's
body then that name is treated as local to the function. This is a
matter of static analysis, and is irrespective of where in the body the
assignment is found.

Of course, you could always test this yourself in interactive mode ...

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Jul 24 '06 #19

P: n/a
On 2006-07-24 16:51:56, danielx wrote:
Gerhard's reply sounded not so confident.
Yes, it is not. It's just the conclusion I drew from my experiments. (I'm
still all wet behind the ears WRT Python...)

As long as there was no write access to the variable, the inner function
could read the value just fine. When there was a write access, the first
read (if it was before the write access) bombed with that error message
that there was a read without a previous write. (Actually, it wasn't a
simple read, it was that "len(var)" access. I'm not sure a normal read
would bomb the same way. But the error message was that it was a read
access without a previous write.)

So that was just my conclusion. It is also consistent with the observation
that variables seem to be known in their scope, even before the location of
their first appearance.
Can we have someone who "really" knows weigh in on this?
That would be nice :)

Gerhard

Jul 24 '06 #20

P: n/a
On 2006-07-24 17:09:24, Steve Holden wrote:
Would I do?
It seems so :)
If there's a binding to a name *anywhere* in the function's body then
that name is treated as local to the function.

This is a matter of static analysis, and is irrespective of where in the
body the assignment is found.
One difficulty I'm having is knowing the proper terminology when looking
for an effect like this. Just someone rephrasing the question using the
proper terms already helps a lot. "Binding" seems to be the keyword here.

It is surprising in the sense that binding seems not to be necessary for
read access.
Going back to the original question... What would be the most common/useful
way to access variables from the outer function for writing from within the
inner function?

Thanks,
Gerhard

Jul 24 '06 #21

P: n/a
Dennis Lee Bieber wrote:
On Mon, 24 Jul 2006 17:35:50 -0300, Gerhard Fiedler <ge*****@gmail.com>
declaimed the following in comp.lang.python:

>>It is surprising in the sense that binding seems not to be necessary for
read access.
It does, I would agree, seem a little counter-intuitive that assignment
(or binding) forces the name to be considered local. That's just one of
Python's features.
>
Binding is the process of attaching the LHS NAME to the OBJECT that
is RHS result.

Python does not use the "mailbox model" of variables. In the mailbox
model (think of a post office sorting table, or the customer boxes in
the lobby), each "box" has one, and only one, name.

A = B

means "take the contents of box B, make a copy of those contents, leave
the original contents in B, and put the copy into box A"

Python has what I refer to as the "Post-It Note Model".

A = B

means "find the box that has a post-it note with 'A' (if there isn't
one, get a blank note and put 'A' on it), take that post-it note and
move it to the box that already has a post-it note with 'B' ". Notice
that this means that THAT box (the object) NOW has TWO Post-It notes,
each with a different "name".
I've never really understood the value of the "Post-It" analogy. Despite
the fact that it allows you to explain that objects can have several
names, it doesn't really help in explaining that the names themselves
live in particular namespaces and have lifetimes largely independent of
the objects to which they refer.

It really seems easier (to me) to explain that names are references or
pointers to values, and that the names live in scopes that can disappear
(for example when a function or method returns). This also allows one to
explain that a function can return references to (one or more) objects,
and if those references are saved by the caller then the lifetime of the
referenced object(s) can be longer than the lifetime of the namespace in
which they were originally created.
Lists/dictionaries/tuples, etc. complicate this a small bit. What
you now have is the "object" (the box with the name of the list on it)
having a lot of pieces of "string" -- each string is stuck to a post-it
note with the final object. This is why

A[1] = B

is not a rebinding of A. It looks for the box with the post-it of A,
then gets the second (0 is first) "string" and follows that string to
the post-it it is stuck on... That end of the string is then moved to
the post-it with the name B
Well here I'd rather simply say that references can also be saved in
container objects, with all the same implications as when they are saved
in names.

This is explained extremely well in Ascher and Lutz's "Learning Python"
(at least in my first edition copy) using diagrams that make it obvious
how objects are created and what their lifetimes are likely to be.

All this business about Post-It notes and pieces of string seems
artificial in the extreme, not to say a little unhelpful. Maybe I've
just been programming too long ...

Perhaps you'd like to try explaining argument passing in terms of
Post-Its? That might be amusing ;-)

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Jul 25 '06 #22

P: n/a
On 2006-07-25 04:06:24, Steve Holden wrote:
Dennis Lee Bieber wrote:
>On Mon, 24 Jul 2006 17:35:50 -0300, Gerhard Fiedler <ge*****@gmail.com>
declaimed the following in comp.lang.python:
>>It is surprising in the sense that binding seems not to be necessary
for read access.
It does, I would agree, seem a little counter-intuitive that assignment
(or binding) forces the name to be considered local. That's just one of
Python's features.
Ok... I can live with that, and thanks for the confirmation that it's not
only me to feel that this is somewhat surprising :)

Surprising for me are actually two things: 1- the fact itself, and 2- that
term "binding", and that whatever it means (I'll have to read more on that,
now that I know the term) is different for read-only and read/write access.

Neither the Post-It note metaphor nor the pointer explanation address that.
Using the Post-It note metaphor, I'm asking myself why the label doesn't
get attached to a different box when reading, but only when writing. ("Just
one of Python's features", I know :) Same thing with the pointer
explanation: AFAIK, no language that uses pointers explicitly does
something similar (that is, the storage the pointer points to is different
depending on whether the pointer gets used for writing and reading, or only
for reading).

Thanks,
Gerhard

Jul 25 '06 #23

P: n/a
Gerhard Fiedler wrote:
On 2006-07-25 04:06:24, Steve Holden wrote:

>>Dennis Lee Bieber wrote:
>>>On Mon, 24 Jul 2006 17:35:50 -0300, Gerhard Fiedler <ge*****@gmail.com>
declaimed the following in comp.lang.python:
It is surprising in the sense that binding seems not to be necessary
for read access.
It does, I would agree, seem a little counter-intuitive that assignment
(or binding) forces the name to be considered local. That's just one of
Python's features.


Ok... I can live with that, and thanks for the confirmation that it's not
only me to feel that this is somewhat surprising :)
Since Python has no "local variable declaration", there must be a rule
to distinguish local names from names living in the enclosing
namespaces. The rule is: unless previously declared 'global' (ie
module-level) with the appropriate statement, any name bound in the
local namespace is local. If declared 'global', it has to exist in the
global namespace.

This was much more simple to understand when we didn't have nested
functions - we mostly had global and local scope. Fact is that we now
have nested functions, but still no statement equivalent to 'global' for
parent namespaces - with the result that we cannot actually rebind
parent's namespace names from within a nested function. But we are still
free to modify any mutable object we can access, so the usual workaround
for immutable objects is to wrap them in a mutable container (list,
dict, etc):

def outer():
def _inner():
outer_var[0] = 'dead'

outer_var = ['parrot']
print "before, outer_var = %s" % outer_var
_inner()
print "after, outer_var = %s" % outer_var

and before you say it: yes, it's a dirty hack.

Surprising for me are actually two things: 1- the fact itself, and 2- that
term "binding", and that whatever it means (I'll have to read more on that,
now that I know the term)
a "binding" is the association of a name and a reference to an object in
a given namespace. It's different from the common notion of "variable",
which is usually a symbolic name for a memory address storing a value
(like a pointer to an object's address).

is different for read-only and read/write access.

What makes the difference is that binding a name to an object in a
namespace creates the name in this namespace (unless the name as been
declared global, cf above). With the result that, the name existing in
the local namespace, it won't be looked up in enclosing namespaces.

Neither the Post-It note metaphor nor the pointer explanation address that.
Using the Post-It note metaphor, I'm asking myself why the label doesn't
get attached to a different box when reading,
The normal lookup rule for names is local namespace then enclosing
namespaces until top-level (module, aka 'global'), then builtins. Else,
you would have to declare as global any "module / function / whatever"
name in each and every function.
but only when writing.
cf above and below.
>("Just
one of Python's features", I know :) Same thing with the pointer
explanation: AFAIK, no language that uses pointers explicitly does
something similar (that is, the storage the pointer points to is different
depending on whether the pointer gets used for writing and reading, or only
for reading).
In most languages, you have to explicitly declare local names one way or
another. Python takes the opposite route : you have to explicitly
declare global names. Since you don't declare local names, binding
creates the name if it doesn't already exists in the local namespace.
HTH
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 25 '06 #24

P: n/a

"Dennis Lee Bieber" <wl*****@ix.netcom.comwrote in message
news:7f********************************@4ax.com...
The names in the parameter list of the "def" statement are bound to
the objects associated with the actual call. After that, they behave
very much as locals... Now -- with defaults it gets a touch trickier...
A function's parameters are not just 'very much as locals', they *are*
locals.
>>def f(x): print locals()
>>f(3)
{'x': 3}

In particular, parameters are just those locals that are initialized in the
call process; it is an error for a parameter name to not become bound to
some object. The default objects fill in the slack when there are not
enough argument objects.
>From the calling side, the arguments are objects to be used in that initial
binding process, either directly or as part of a new collective object. It
is an error for an argument to not be used. The calling code does not care
about the parameter names, but just their number and nature.

So one can think of calling as cross-namespace name binding followed by
control transfer. Returning is similar except that return objects may
ignored or bound to slots rather than names.

Terry Jan Reedy

Jul 25 '06 #25

P: n/a
On 2006-07-25 13:33:40, Dennis Lee Bieber wrote:
>Surprising for me are actually two things: 1- the fact itself, and 2- that
term "binding", and that whatever it means (I'll have to read more on that,
now that I know the term) is different for read-only and read/write access.
Binding only happens when the bare name is on the LHS of an assignment
(or, to complicate matters, passed as an argument).
This makes a lot more sense now.

Binding has nothing to do with "read-only" vs "read/write" access.
Isn't being on the LHS the only way to write to a non-mutable object? Are
there situations where binding happens without writing to a variable? Are
there write accesses to non-mutable objects where the name is not on the
LHS?

Reading is a look-up operation -- you are looking for the object that
"currently" has the "post-it" (which is the Name) attached to it.
Thanks, to you and Bruno. I think I got this now, and also why.

(And see, here you are talking about reading... see my questions above.)

Gerhard

Jul 25 '06 #26

P: n/a

Bruno Desthuilliers wrote:
Gerhard Fiedler wrote:
On 2006-07-25 04:06:24, Steve Holden wrote:

>Dennis Lee Bieber wrote:

On Mon, 24 Jul 2006 17:35:50 -0300, Gerhard Fiedler <ge*****@gmail.com>
declaimed the following in comp.lang.python:
It is surprising in the sense that binding seems not to be necessary
for read access.

It does, I would agree, seem a little counter-intuitive that assignment
(or binding) forces the name to be considered local. That's just one of
Python's features.

Ok... I can live with that, and thanks for the confirmation that it's not
only me to feel that this is somewhat surprising :)

Since Python has no "local variable declaration", there must be a rule
to distinguish local names from names living in the enclosing
namespaces. The rule is: unless previously declared 'global' (ie
module-level) with the appropriate statement, any name bound in the
local namespace is local. If declared 'global', it has to exist in the
global namespace.

This was much more simple to understand when we didn't have nested
functions - we mostly had global and local scope. Fact is that we now
have nested functions, but still no statement equivalent to 'global' for
parent namespaces - with the result that we cannot actually rebind
parent's namespace names from within a nested function. But we are still
free to modify any mutable object we can access, so the usual workaround
for immutable objects is to wrap them in a mutable container (list,
dict, etc):

def outer():
def _inner():
outer_var[0] = 'dead'

outer_var = ['parrot']
print "before, outer_var = %s" % outer_var
_inner()
print "after, outer_var = %s" % outer_var

and before you say it: yes, it's a dirty hack.

Surprising for me are actually two things: 1- the fact itself, and 2- that
term "binding", and that whatever it means (I'll have to read more on that,
now that I know the term)

a "binding" is the association of a name and a reference to an object in
a given namespace. It's different from the common notion of "variable",
which is usually a symbolic name for a memory address storing a value
(like a pointer to an object's address).
Wait, I'm not sure I see the difference. Isn't "reference" ~ "C
pointer". Are you saying Python variables don't hold references to
"actual" Python objects? That idea has been working well for me so far.
>
is different for read-only and read/write access.

What makes the difference is that binding a name to an object in a
namespace creates the name in this namespace (unless the name as been
declared global, cf above). With the result that, the name existing in
the local namespace, it won't be looked up in enclosing namespaces.

Neither the Post-It note metaphor nor the pointer explanation address that.
Using the Post-It note metaphor, I'm asking myself why the label doesn't
get attached to a different box when reading,

The normal lookup rule for names is local namespace then enclosing
namespaces until top-level (module, aka 'global'), then builtins. Else,
you would have to declare as global any "module / function / whatever"
name in each and every function.
but only when writing.

cf above and below.
("Just
one of Python's features", I know :) Same thing with the pointer
explanation: AFAIK, no language that uses pointers explicitly does
something similar (that is, the storage the pointer points to is different
depending on whether the pointer gets used for writing and reading, or only
for reading).

In most languages, you have to explicitly declare local names one way or
another. Python takes the opposite route : you have to explicitly
declare global names. Since you don't declare local names, binding
creates the name if it doesn't already exists in the local namespace.
HTH
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 27 '06 #27

P: n/a
On 2006-07-25, Bruno Desthuilliers <on***@xiludom.growrote:
Gerhard Fiedler wrote:
>On 2006-07-25 04:06:24, Steve Holden wrote:
Since Python has no "local variable declaration", there must be a rule
to distinguish local names from names living in the enclosing
namespaces. The rule is: unless previously declared 'global' (ie
module-level) with the appropriate statement, any name bound in the
local namespace is local. If declared 'global', it has to exist in the
global namespace.

This was much more simple to understand when we didn't have nested
functions - we mostly had global and local scope.
But having only a global an local scope, didn't prevent nested
functions. The nested functions just didn't have nested scopes
and that had it's own problems.

--
Antoon Pardon
Jul 27 '06 #28

P: n/a
Gerhard Fiedler wrote:
Going back to the original question... What would be the most
common/useful way to access variables from the outer function for writing
from within the inner function?
I've done something like this (which doesn't look very nice)

def myfunc():

tok = ['']

def inner():
tok[0] += 'hi'
...
tok[0] = 'foo'

inner()
print tok[0]

--
Jeremy Sanders
http://www.jeremysanders.net/
Jul 27 '06 #29

P: n/a
danielx wrote:
Bruno Desthuilliers wrote:
(snip)
>>
>>>Surprising for me are actually two things: 1- the fact itself, and 2- that
term "binding", and that whatever it means (I'll have to read more on that,
now that I know the term)

a "binding" is the association of a name and a reference to an object in
a given namespace. It's different from the common notion of "variable",
which is usually a symbolic name for a memory address storing a value
(like a pointer to an object's address).


Wait, I'm not sure I see the difference. Isn't "reference" ~ "C
pointer".
For a very large definition of '~' !-)
Are you saying Python variables don't hold references to
"actual" Python objects?
Exactly.
That idea has been working well for me so far.
It can only take you so far. Now it's time you know the truth: there are
*no* 'variables' in Python (hence the term 'binding').

What you really have is (somewhat simplified, of course) a dict with
names as keys and objects references (think of 'smart' pointers) as
values. So the name doesn't 'hold' anything - it's really nothing more
than a name. And the object doesn't know nothing about which names it's
bound to.
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 27 '06 #30

P: n/a
On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
danielx wrote:
>Bruno Desthuilliers wrote:
(snip)
>>>
Surprising for me are actually two things: 1- the fact itself, and 2- that
term "binding", and that whatever it means (I'll have to read more on that,
now that I know the term)

a "binding" is the association of a name and a reference to an object in
a given namespace. It's different from the common notion of "variable",
which is usually a symbolic name for a memory address storing a value
(like a pointer to an object's address).


Wait, I'm not sure I see the difference. Isn't "reference" ~ "C
pointer".

For a very large definition of '~' !-)
>Are you saying Python variables don't hold references to
"actual" Python objects?

Exactly.
>That idea has been working well for me so far.

It can only take you so far. Now it's time you know the truth: there are
*no* 'variables' in Python (hence the term 'binding').
That depends on what you want to mean with the term. IMO 'variables'
in python behave sufficiently similar as in other languages to use
the term.
What you really have is (somewhat simplified, of course) a dict with
names as keys and objects references (think of 'smart' pointers) as
values.
That is just an implementation issue. Nothing prevents variables to
be associated with an index in a list.
So the name doesn't 'hold' anything - it's really nothing more
than a name.
In a language like C the name doesn't hold anything either.
The name is just a way for refering to a memory space which
will hold something.
And the object doesn't know nothing about which names it's
bound to.
In a language like C, the value '3' doesn't know which variables
will hold it either.

--
Antoon Pardon
Jul 27 '06 #31

P: n/a
On 2006-07-27 09:42:16, Bruno Desthuilliers wrote:
>Are you saying Python variables don't hold references to "actual" Python
objects?

Exactly.
>That idea has been working well for me so far.

It can only take you so far. Now it's time you know the truth: there are
*no* 'variables' in Python (hence the term 'binding').

What you really have is (somewhat simplified, of course) a dict with
names as keys and objects references (think of 'smart' pointers) as
values. So the name doesn't 'hold' anything - it's really nothing more
than a name. And the object doesn't know nothing about which names it's
bound to.
I see that, and this thread and your and others explanations have been
helpful in seeing deeper.

But can't this be expressed -- maybe -- as the variable name "holding" the
reference that is associated to it through the dict? Aside the explicit
mentioning of the dict (which I agree is in itself a value, especially
since that dict exists and can be accessed as dict), the image seems to
provide the same analogy.

Gerhard

Jul 27 '06 #32

P: n/a
Antoon Pardon wrote:
On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
>>danielx wrote:
>>>Bruno Desthuilliers wrote:

(snip)
>>>>>Surprising for me are actually two things: 1- the fact itself, and 2- that
>term "binding", and that whatever it means (I'll have to read more on that,
>now that I know the term)

a "binding" is the association of a name and a reference to an object in
a given namespace. It's different from the common notion of "variable",
which is usually a symbolic name for a memory address storing a value
(like a pointer to an object's address).
Wait, I'm not sure I see the difference. Isn't "reference" ~ "C
pointer".

For a very large definition of '~' !-)

>>>Are you saying Python variables don't hold references to
"actual" Python objects?

Exactly.

>>>That idea has been working well for me so far.

It can only take you so far. Now it's time you know the truth: there are
*no* 'variables' in Python (hence the term 'binding').


That depends on what you want to mean with the term. IMO 'variables'
in python behave sufficiently similar as in other languages
Which ones ? C ? or Lisp ? Or Haskell ?
to use
the term.
IYO.
>
>>What you really have is (somewhat simplified, of course) a dict with
names as keys and objects references (think of 'smart' pointers) as
values.


That is just an implementation issue. Nothing prevents variables to
be associated with an index in a list.
Do you understand what "somewhat simplified" means ?
>
>>So the name doesn't 'hold' anything - it's really nothing more
than a name.


In a language like C the name doesn't hold anything either.
Yes : it holds type and storage class informations too.
The name is just a way for refering to a memory space which
will hold something.
The name is a symbolic name for a memory address in which bits will be
stored (and the type information is used to know how to interpret the
bits at this address - I leave storage class problems aside). There's a
direct translation from symbolic name to memory address to bits. Which
is not the case in Python...
>
>>And the object doesn't know nothing about which names it's
bound to.


In a language like C, the value '3' doesn't know which variables
will hold it either.
Indeed. Now could you tell us what was your point, exactly ?
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 27 '06 #33

P: n/a
On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
Antoon Pardon wrote:
>On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
>>>danielx wrote:

Bruno Desthuilliers wrote:
(snip)

>>Surprising for me are actually two things: 1- the fact itself, and 2- that
>>term "binding", and that whatever it means (I'll have to read more on that,
>>now that I know the term)
>
>a "binding" is the association of a name and a reference to an object in
>a given namespace. It's different from the common notion of "variable",
>which is usually a symbolic name for a memory address storing a value
>(like a pointer to an object's address).
Wait, I'm not sure I see the difference. Isn't "reference" ~ "C
pointer".

For a very large definition of '~' !-)
Are you saying Python variables don't hold references to
"actual" Python objects?

Exactly.
That idea has been working well for me so far.

It can only take you so far. Now it's time you know the truth: there are
*no* 'variables' in Python (hence the term 'binding').


That depends on what you want to mean with the term. IMO 'variables'
in python behave sufficiently similar as in other languages

Which ones ? C ? or Lisp ? Or Haskell ?
Whatever, if both C and Lisp can both talk about variables, I don't
see why python can't
>to use
the term.

IYO.
So? The statement that python doesn't has variables is just your opinion.
>>>What you really have is (somewhat simplified, of course) a dict with
names as keys and objects references (think of 'smart' pointers) as
values.


That is just an implementation issue. Nothing prevents variables to
be associated with an index in a list.

Do you understand what "somewhat simplified" means ?
Not the difference between a list and a dictionary.
>>>So the name doesn't 'hold' anything - it's really nothing more
than a name.


In a language like C the name doesn't hold anything either.

Yes : it holds type and storage class informations too.
If you want so. But that is totally irrelevant for considering
something as a variable or not. If someone would wish to extend
python with a type system, so that a variable could be associated
with type information, it would not essentially change what
one could do with an identiefier in python.

Like wise one could make a C-like language without type and
storage class information associated with identifiers. Variables
would essentially still behave the same.
>The name is just a way for refering to a memory space which
will hold something.

The name is a symbolic name for a memory address in which bits will be
stored (and the type information is used to know how to interpret the
bits at this address - I leave storage class problems aside). There's a
direct translation from symbolic name to memory address to bits.
That doesn't need to be. A C-implementation could use directories.
Most implementations don't but that is just because it would slow
performance, but perfectly legal C-behaviour would be possible.

Besides what you say isn't true in general. There is no direct
translation from a local name to memory address. The same name
can refer to a different memory address on different invocations
of the function.
Which is not the case in Python...
An implementation detail.
>>>And the object doesn't know nothing about which names it's
bound to.


In a language like C, the value '3' doesn't know which variables
will hold it either.

Indeed. Now could you tell us what was your point, exactly ?
Just showing that the object not knowing which identifiers
it is bound to is irrelevant.

--
Antoon Pardon
Jul 27 '06 #34

P: n/a
Antoon Pardon wrote:
On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
(snip)
>>>>It can only take you so far. Now it's time you know the truth: there are
*no* 'variables' in Python (hence the term 'binding').
That depends on what you want to mean with the term. IMO 'variables'
in python behave sufficiently similar as in other languages

Which ones ? C ? or Lisp ? Or Haskell ?


Whatever, if both C and Lisp can both talk about variables, I don't
see why python can't
Guess where the term "binding" comes from.
>
>>>to use
the term.

IYO.


So? The statement that python doesn't has variables is just your opinion.
The statement that "Python doesn't has variables" is meant to emphasis
the very difference between C-like variables and Python bindings.
>
>>>>What you really have is (somewhat simplified, of course) a dict with
names as keys and objects references (think of 'smart' pointers) as
values.
That is just an implementation issue.
yes, your favourite argument ever.
>>Nothing prevents variables to
be associated with an index in a list.

Do you understand what "somewhat simplified" means ?


Not the difference between a list and a dictionary.
You don't understand the difference between a list and a dict ?

FWIW, the module and the classes namespaces are really implemented with
dicts. Functions namespaces are not IIRC, but I can't find the link no more.
>
>>>>So the name doesn't 'hold' anything - it's really nothing more
than a name.
In a language like C the name doesn't hold anything either.

Yes : it holds type and storage class informations too.


If you want so. But that is totally irrelevant for considering
something as a variable or not.
This is relevant when talking about the difference between C variables
and Python bindings.
If someone would wish to extend
python with a type system,
In case you don't know, it already has one.
>
>>>The name is just a way for refering to a memory space which
will hold something.

The name is a symbolic name for a memory address in which bits will be
stored (and the type information is used to know how to interpret the
bits at this address - I leave storage class problems aside). There's a
direct translation from symbolic name to memory address to bits.

That doesn't need to be. A C-implementation could use directories.
"could", yes. But I'm not talking about language grammar.
>>Indeed. Now could you tell us what was your point, exactly ?

Just showing that the object not knowing which identifiers
it is bound to is irrelevant.
Someone in this thread used a 'post-it' metaphor that more or less
implied that the name was 'post-it'ed' on the object. Which is not the
case. Hence my precision on this.

And I still fail to get the whole point of your post.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 27 '06 #35

P: n/a
Gerhard Fiedler wrote:
On 2006-07-27 09:42:16, Bruno Desthuilliers wrote:

>>>Are you saying Python variables don't hold references to "actual" Python
objects?

Exactly.

>>>That idea has been working well for me so far.

It can only take you so far. Now it's time you know the truth: there are
*no* 'variables' in Python (hence the term 'binding').

What you really have is (somewhat simplified, of course) a dict with
names as keys and objects references (think of 'smart' pointers) as
values. So the name doesn't 'hold' anything - it's really nothing more
than a name. And the object doesn't know nothing about which names it's
bound to.


I see that, and this thread and your and others explanations have been
helpful in seeing deeper.

But can't this be expressed -- maybe -- as the variable name "holding" the
reference
s/the/a/
that is associated to it through the dict? Aside the explicit
mentioning of the dict (which I agree is in itself a value, especially
since that dict exists and can be accessed as dict), the image seems to
provide the same analogy.
What bother me with the "hold" term is that I understand it as meaning
that the name is some kind of container by itself - which it is not.
Consider the following:

d = dict()
d['name'] = 'parrot'

Would you say that the string "name" 'holds a reference' to the string
"parrot" ? Obviously not - it's the dict that holds this reference.

My 2 cents...
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 27 '06 #36

P: n/a
On 2006-07-27 13:44:29, Bruno Desthuilliers wrote:
What bother me with the "hold" term is that I understand it as meaning
that the name is some kind of container by itself - which it is not.
Consider the following:

d = dict()
d['name'] = 'parrot'

Would you say that the string "name" 'holds a reference' to the string
"parrot" ? Obviously not - it's the dict that holds this reference.
Right... I think in some cases it is normal to say in such a situation that
"'name' refers to 'parrot'" (for example when talking about the problem
domain, rather than the implementation) -- independently of the
implementation of the "reference" (which could be a pointer, or a
dictionary, or a database table).

But, I'm a convert already :)

Gerhard

Jul 27 '06 #37

P: n/a
On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
Antoon Pardon wrote:
>On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
(snip)
>>>>>It can only take you so far. Now it's time you know the truth: there are
>*no* 'variables' in Python (hence the term 'binding').
That depends on what you want to mean with the term. IMO 'variables'
in python behave sufficiently similar as in other languages

Which ones ? C ? or Lisp ? Or Haskell ?


Whatever, if both C and Lisp can both talk about variables, I don't
see why python can't

Guess where the term "binding" comes from.
I don't see how that is relevant.
>>>>to use
the term.

IYO.


So? The statement that python doesn't has variables is just your opinion.

The statement that "Python doesn't has variables" is meant to emphasis
the very difference between C-like variables and Python bindings.
And why should that be relevant? Lisp-like variables are different
from C-like variables, but that doesn't stop us from using the
word "variable". So why should the difference between C-like
variables and Python bindings be important enough to no longer
use that word.
>>>>>What you really have is (somewhat simplified, of course) a dict with
>names as keys and objects references (think of 'smart' pointers) as
>values.
That is just an implementation issue.

yes, your favourite argument ever.
What is your point? That it is my favourite argument ever doesn't
make it wrong or invalid. If you have an issue with it, bring
your arguments. The fact is that if you don't want to use the
word variable, you can't rely on current implementation details,
because implementation details can change without the language
changing.
FWIW, the module and the classes namespaces are really implemented with
dicts. Functions namespaces are not IIRC, but I can't find the link no more.
If you use __slots__, the class namespaces is implemented as a list.
Unless when you add __dict__ to the slots, in that case you have
some kind of hybrid system.
>>>>>So the name doesn't 'hold' anything - it's really nothing more
>than a name.
In a language like C the name doesn't hold anything either.

Yes : it holds type and storage class informations too.


If you want so. But that is totally irrelevant for considering
something as a variable or not.

This is relevant when talking about the difference between C variables
and Python bindings.
It is irrelevant because the word "variable" is used in a lot of
different languages. A lot of them with behaviour closer to python
than to C. The difference between C variables and Python bindings
is only relevant if it can give you an argument for why we shouldn't
use "variable" when discussing python.
>If someone would wish to extend
python with a type system,

In case you don't know, it already has one.
I'll be more clearer: If someone wants to extend python with
a kind of static typing, where you could limit names binding only
to objects of a certain number of classes, it wouldn't essentially
change what could be done with names in python, but the names would now
hold type information too. So whether a name carries type information
or not, has little relevance to whether the term "variable" is appropiate
or not.
>>>>The name is just a way for refering to a memory space which
will hold something.

The name is a symbolic name for a memory address in which bits will be
stored (and the type information is used to know how to interpret the
bits at this address - I leave storage class problems aside). There's a
direct translation from symbolic name to memory address to bits.

That doesn't need to be. A C-implementation could use directories.

"could", yes. But I'm not talking about language grammar.
Neither am I, I am talking about language semantics.
If a C-implementation could use directories, that means
that directories can be used to capture the C-semantics.
So whether the implementation uses direct translation
from name to memory to bits or uses directories, it
doesn't change one bit what one can do with a variable
in the language.

Besides, you don't seem to have a problem talking about
Lisp-variables, and Lisp-variables don't have such
a direct translation from symbolic name to memory
address either. So this specific detail of most C-implementations
seems mostly irrelevant to me.

--
Antoon Pardon
Jul 27 '06 #38

P: n/a
On 2006-07-27, Dennis Lee Bieber <wl*****@ix.netcom.comwrote:
On 27 Jul 2006 14:11:35 GMT, Antoon Pardon <ap*****@forel.vub.ac.be>
declaimed the following in comp.lang.python:
>In a language like C the name doesn't hold anything either.
The name is just a way for refering to a memory space which
will hold something.
Except for one difference... In C (and most other languages) that
memory space is FIXED -- name "X" ALWAYS refers to memory space "Y".
Even in the case of a C pointer -- "P" always refers to one memory space
"p" wherein the contents of that memory space is a user-accessible
reference to some other memory space; to actually get to the object one
must dereference "P" using "*P" or "P->" type notation

In Python, even the location of the "name" may vary -- if you "del
name" then do some operations and rebind "name", the new "name" itself
could be somewhere else in memory.
You are right. That is a difference between Python and C. But How
important is that difference? Should I design a C-like language
with the parror virtual machine in mind as target architecture:

http://www.parrotcode.org/

Would that difference be important enough to no longer talk about
variables? IMO we also talk about Lisp- and Smalltalk variables
and AFAIK these behave more like Python than C. If "variables"
is used in such languages, why should the term not be appropiate
for Python.

--
Antoon Pardon
Jul 27 '06 #39

P: n/a
On 2006-07-27 14:15:34, Dennis Lee Bieber wrote:
>In a language like C the name doesn't hold anything either. The name is
just a way for refering to a memory space which will hold something.
Except for one difference... In C (and most other languages) that
memory space is FIXED -- name "X" ALWAYS refers to memory space "Y".
Not really fixed, at least not for local variables. They sit at variable
places, which can be (and usually are) different for every invocation of a
function. Maybe "stack-fixed"...

Not sure this is relevant, but I felt it needed to be said :)

In Python, even the location of the "name" may vary -- if you "del
name" then do some operations and rebind "name", the new "name" itself
could be somewhere else in memory.
In this respect, a Python var is similar to a C pointer var. The same thing
you are describing here can be done with a C pointer. Allocate storage
("bind" it) and have a pointer referencing it. Do something with it.
Deallocate it ("del it"). Allocate other storage and have the same pointer
referencing it ("rebind it"). The referenced area is somewhere else now
(usually).

Gerhard

Jul 27 '06 #40

P: n/a
Antoon Pardon a écrit :
On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
>>Antoon Pardon wrote:
>>>On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:

(snip)
>>>>>>It can only take you so far. Now it's time you know the truth: there are
>>*no* 'variables' in Python (hence the term 'binding').
>
>
>That depends on what you want to mean with the term. IMO 'variables'
>in python behave sufficiently similar as in other languages

Which ones ? C ? or Lisp ? Or Haskell ?
Whatever, if both C and Lisp can both talk about variables, I don't
see why python can't

Guess where the term "binding" comes from.


I don't see how that is relevant.
No ?
>>>
So? The statement that python doesn't has variables is just your opinion.

The statement that "Python doesn't has variables" is meant to emphasis
the very difference between C-like variables and Python bindings.


And why should that be relevant?
Because the person I was replying to asked for the difference between
C-like variables (which are mostly symbolic names for memory addresses
storing bits) and Python's variable (which are mostly keys associated to
a reference to an object).
Lisp-like variables are different
from C-like variables,
indeed.
but that doesn't stop us from using the
word "variable". So why should the difference between C-like
variables and Python bindings be important enough to no longer
use that word.
Use the word that you want, I don't give a damn. I can't help if you're
clueless enough to understand why I wanted to emphasis the difference.
>>>>>>What you really have is (somewhat simplified, of course) a dict with
>>names as keys and objects references (think of 'smart' pointers) as
>>values.
>
>
>That is just an implementation issue.

yes, your favourite argument ever.


What is your point? That it is my favourite argument ever doesn't
make it wrong or invalid.
Does it occurs to you that most languages are designed with specific
requirements in mind ? (well, for those that are designed at least). And
that a good part of these requirements are about or closely related to
implementation issues ?
If you have an issue with it, bring
your arguments. The fact is that if you don't want to use the
word variable,
I use it everyday.
you can't rely on current implementation details,
because implementation details can change without the language
changing.
Yeah, great. Now you're done with theory, let's get pragmatic.
>
>>FWIW, the module and the classes namespaces are really implemented with
dicts. Functions namespaces are not IIRC, but I can't find the link no more.


If you use __slots__, the class namespaces is implemented as a list.
Unless when you add __dict__ to the slots, in that case you have
some kind of hybrid system.
<aol>
Implementation detail.
</aol>
>>>>>>So the name doesn't 'hold' anything - it's really nothing more
>>than a name.
>
>
>In a language like C the name doesn't hold anything either.

Yes : it holds type and storage class informations too.
If you want so. But that is totally irrelevant for considering
something as a variable or not.

This is relevant when talking about the difference between C variables
and Python bindings.


It is irrelevant because the word "variable" is used in a lot of
different languages. A lot of them with behaviour closer to python
than to C. The difference between C variables and Python bindings
is only relevant if it can give you an argument for why we shouldn't
use "variable" when discussing python.
Oh, my...
>
>>>If someone would wish to extend
python with a type system,

In case you don't know, it already has one.


I'll be more clearer: If someone wants to extend python with
a kind of static typing,
I dont.
>>>>>The name is just a way for refering to a memory space which
>will hold something.

The name is a symbolic name for a memory address in which bits will be
stored (and the type information is used to know how to interpret the
bits at this address - I leave storage class problems aside). There's a
direct translation from symbolic name to memory address to bits.
That doesn't need to be. A C-implementation could use directories.

"could", yes. But I'm not talking about language grammar.


Neither am I, I am talking about language semantics.
If a C-implementation could use directories, that means
that directories can be used to capture the C-semantics.
I don't care, and I really doubt anyone working on a C implementation
cares much. C has been designed to be as simple as possible to
implement, as close to the hardware as possible, and as fast as
possible. It has been designed for system programming - actually to make
Unix portable to other architectures. It's very obvious for anyone with
a not too limited understanding that C design is very closely related to
these goals.
So whether the implementation uses direct translation
from name to memory to bits or uses directories, it
doesn't change one bit what one can do with a variable
in the language.
fine.
Besides, you don't seem to have a problem talking about
Lisp-variables, and Lisp-variables don't have such
a direct translation from symbolic name to memory
address either. So this specific detail of most C-implementations
seems mostly irrelevant to me.
The fact that it seems irrelevant to you seems totally irrelevant to me.
Good night.

Jul 27 '06 #41

P: n/a
Gerhard Fiedler a écrit :
On 2006-07-27 13:44:29, Bruno Desthuilliers wrote:

>>What bother me with the "hold" term is that I understand it as meaning
that the name is some kind of container by itself - which it is not.
Consider the following:

d = dict()
d['name'] = 'parrot'

Would you say that the string "name" 'holds a reference' to the string
"parrot" ? Obviously not - it's the dict that holds this reference.


Right... I think in some cases it is normal to say in such a situation that
"'name' refers to 'parrot'" (for example when talking about the problem
domain, rather than the implementation) -- independently of the
implementation of the "reference" (which could be a pointer, or a
dictionary, or a database table).
Of course. And FWIW, in day to day life, I use the word 'variable' like
anyone else !-)
But, I'm a convert already :)

Gerhard
Jul 27 '06 #42

P: n/a
Gerhard Fiedler a écrit :
On 2006-07-25 13:33:40, Dennis Lee Bieber wrote:

>>>Surprising for me are actually two things: 1- the fact itself, and 2- that
term "binding", and that whatever it means (I'll have to read more on that,
now that I know the term) is different for read-only and read/write access.

Binding only happens when the bare name is on the LHS of an assignment
(or, to complicate matters, passed as an argument).

This makes a lot more sense now.
>>Binding has nothing to do with "read-only" vs "read/write" access.


Isn't being on the LHS the only way to write to a non-mutable object?
You *don't* "write to a non-mutable object". You rebind the name to
another object (mutable or not, that's not the problem).
>Are
there situations where binding happens without writing to a variable?
binding and "assignment" (what you call "writing to a variable") are the
very same operation.
Are
there write accesses to non-mutable objects
No.
where the name is not on the
LHS?
Doesn't matter when it comes to immutable objects. As the name imply,
you cannot modify an immutable object once it's created. Rebiding a name
bound to an immutable object doesn't impact the object[1], it just
makes the name refers to another object.
[1] or, to be more exact, it only decreases the object's reference
count, which can lead to the object being disposed of...
Jul 27 '06 #43

P: n/a
Gerhard Fiedler a écrit :
On 2006-07-27 14:15:34, Dennis Lee Bieber wrote:

>>>In a language like C the name doesn't hold anything either. The name is
just a way for refering to a memory space which will hold something.

Except for one difference... In C (and most other languages) that
memory space is FIXED -- name "X" ALWAYS refers to memory space "Y".


Not really fixed, at least not for local variables. They sit at variable
places, which can be (and usually are) different for every invocation of a
function. Maybe "stack-fixed"...

Not sure this is relevant, but I felt it needed to be said :)
>> In Python, even the location of the "name" may vary -- if you "del
name" then do some operations and rebind "name", the new "name" itself
could be somewhere else in memory.


In this respect, a Python var is similar to a C pointer var. The same thing
you are describing here can be done with a C pointer. Allocate storage
("bind" it) and have a pointer referencing it. Do something with it.
Deallocate it ("del it"). Allocate other storage and have the same pointer
referencing it ("rebind it"). The referenced area is somewhere else now
(usually).
Yes, Python references and C pointers are closely related.

But a C pointer (I mean the pointer itself, not what it points to) is
still a C variable. It has a 'lifetime-fixed' memory address -
deallocating the memory block whose address is stored in the pointer and
assigning NULL to the pointer won't change the pointer's address, nor
make the pointer variable disappear from the current scope FWIW - and an
'immediate' value - which is either garbage, NULL or a (possibly invalid
!-) memory address.

While in Python, deleting a name *really* delete the name from the
current namespace - but not necessarily the object that was bound to the
name:

Python 2.4.1 (#1, Jul 23 2005, 00:37:37)
[GCC 3.3.4 20040623 (Gentoo Linux 3.3.4-r1, ssp-3.3.2-2, pie-8.7.6)] on
linux2
Type "help", "copyright", "credits" or "license" for more information.
>>a = []
del a
a
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'a' is not defined
>>a = []
id(a)
1078043756
>>b = a
id(b)
1078043756
>>del a
b
[]
>>id(b)
1078043756
>>>
NB: in CPython, id(<somename>) returns the address of the object bound
to <somename>.

HTH
Jul 27 '06 #44

P: n/a
On 2006-07-27 17:10:55, Bruno Desthuilliers wrote:
>Isn't being on the LHS the only way to write to a non-mutable object?

You *don't* "write to a non-mutable object". You rebind the name to
another object (mutable or not, that's not the problem).
Ok, sloppy writing (sloppy thinking, or probably incomplete understanding
:) on my part. Let me rephrase the three original questions:
>Isn't being on the LHS the only way to write to a non-mutable object? Are
there situations where binding happens without writing to a variable? Are
there write accesses to non-mutable objects where the name is not on the
LHS?
Rephrased as:

Isn't being on the LHS (of an assignment) the only way to (re)bind a
variable? Are there situations where binding happens without an explicit
assignment with the variable name being on the LHS? Can the object
referenced by a variable name get changed without the variable name
appearing on the LHS?

(I hope I got this right now... asking the correct questions is not so easy
sometimes :)

Thanks,
Gerhard

Jul 28 '06 #45

P: n/a
Gerhard Fiedler a écrit :
On 2006-07-27 17:10:55, Bruno Desthuilliers wrote:

>>>Isn't being on the LHS the only way to write to a non-mutable object?

You *don't* "write to a non-mutable object". You rebind the name to
another object (mutable or not, that's not the problem).


Ok, sloppy writing (sloppy thinking, or probably incomplete understanding
:) on my part. Let me rephrase the three original questions:

>>>Isn't being on the LHS the only way to write to a non-mutable object? Are
there situations where binding happens without writing to a variable? Are
there write accesses to non-mutable objects where the name is not on the
LHS?


Rephrased as:

Isn't being on the LHS (of an assignment) the only way to (re)bind a
variable?
<pedantic>
s/variable/name/
</pedantic>
Are there situations where binding happens without an explicit
assignment with the variable name being on the LHS?
Assignment aside, binding occurs:

1/ on evaluation of import, class and def statement
see Dennis answer for an example with import. Here are examples with def
and class:
>>a
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'a' is not defined
>>a = []
a
[]
>>id(a)
1078043820
>>def a(): pass
....
>>a
<function a at 0x404162cc>
>>id(a)
1078026956
>>class a: pass
....
>>a
<class __main__.a at 0x4040dadc>
>>id(a)
1077992156
>>>
2/ on function call for the function's arguments

This second case won't obviously *re*bind existing names in the
function's namespace, nor in the caller namespace, so we don't care here.
3/ as a result of a list comp or for loop:
>>a
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'a' is not defined
>>for a in range(3): pass
....
>>a
2
>>b
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'b' is not defined
>>[b for b in range(3)]
[0, 1, 2]
>>b
2
>>>
AFAICT and IIRC, this should cover most cases - please someone correct
me if I forgot something here...

Can the object
referenced by a variable name get changed without the variable name
appearing on the LHS?
>>a = []
id(a)
1078043820
>>def change(l):
.... l.append(42)
....
>>change(a)
a
[42]
>>id(a)
1078043820
>>>
First assignment aside, the *name* 'a' is never on the LHS of an
assignment, yet the object referenced by name 'a' got 'changed' : it was
initially empty, after call to change() it contains an int.

Yes, I know, this is not what you meant (and no, name 'a' has not been
rebound) - but that's really what you asked : the object referenced by
name 'a' got changed without name 'a' being on the LHS !-) Hence the
emphasis on the difference between mutating (modifying/changing/...) an
object and rebinding a name...

I think your intented question was more like : "can a name be rebound
without that name being on the LHS of an assignment", and it's addressed
above
(I hope I got this right now...
Almost !-)
asking the correct questions is not so easy
sometimes :)
Indeed !-)
Jul 28 '06 #46

P: n/a
On 2006-07-28 04:07:20, Bruno Desthuilliers wrote:
Gerhard Fiedler a écrit :
>Isn't being on the LHS (of an assignment) the only way to (re)bind a
variable?

<pedantic>
s/variable/name/
</pedantic>
Ok, I missed this one :)
>Are there situations where binding happens without an explicit
assignment with the variable name being on the LHS?

Assignment aside, binding occurs:

1/ on evaluation of import, class and def statement
2/ on function call for the function's arguments
3/ as a result of a list comp or for loop:
Sounds intuitive enough.
>Can the object referenced by a variable name get changed without the
variable name appearing on the LHS?
>>a = []
>>id(a)
1078043820
>>def change(l):
... l.append(42)
...
>>change(a)
>>a
[42]
>>id(a)
1078043820
>>>

First assignment aside, the *name* 'a' is never on the LHS of an
assignment, yet the object referenced by name 'a' got 'changed' : it was
initially empty, after call to change() it contains an int.

Yes, I know, this is not what you meant (and no, name 'a' has not been
rebound) - but that's really what you asked : the object referenced by
name 'a' got changed without name 'a' being on the LHS !-)
What I meant here is whether the object can be a different one than before
(the object gets changed like a shirt before dinner, not like the color of
crabs during cooking), without it being caused by being on the LHS of an
assignment (or any of the other possibilities you listed above). That was
more an ambiguity in the language...
I think your intented question was more like : "can a name be rebound
without that name being on the LHS of an assignment", [...]
Yes.
and it's addressed above
I'll have to experiment a bit and come up with an example of what I'm
thinking of. But it seems that what I was thinking of doesn't make sense in
the light of my better understanding of binding :)

Thanks for your help. Binding seems to be one of the more crucial concepts
to master before understanding how Python works. One of the first things I
wondered (this is slightly related) is whether it wouldn't be really good
to make the difference between mutable and immutable objects more obvious.

Gerhard

Jul 28 '06 #47

P: n/a
On 2006-07-27, Bruno Desthuilliers <bd*****************@free.quelquepart.frwrote:
Antoon Pardon a écrit :
>On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
>>>Antoon Pardon wrote:

On 2006-07-27, Bruno Desthuilliers <on***@xiludom.growrote:
(snip)

>>>It can only take you so far. Now it's time you know the truth: there are
>>>*no* 'variables' in Python (hence the term 'binding').
>>
>>
>>That depends on what you want to mean with the term. IMO 'variables'
>>in python behave sufficiently similar as in other languages
>
>Which ones ? C ? or Lisp ? Or Haskell ?
Whatever, if both C and Lisp can both talk about variables, I don't
see why python can't

Guess where the term "binding" comes from.


I don't see how that is relevant.

No ?
Do you actually have a point? I doubt it because I would otherwise
have expected that you would actually have presented it by now.
>>>>
So? The statement that python doesn't has variables is just your opinion.

The statement that "Python doesn't has variables" is meant to emphasis
the very difference between C-like variables and Python bindings.


And why should that be relevant?

Because the person I was replying to asked for the difference between
C-like variables (which are mostly symbolic names for memory addresses
storing bits) and Python's variable (which are mostly keys associated to
a reference to an object).
That is no reason to say that python has no variables. If someone would
explain the difference between objects in some other language and
objects in python I wouldn't accept the statement: "python has no
objects" either.
>Lisp-like variables are different
from C-like variables,

indeed.
>but that doesn't stop us from using the
word "variable". So why should the difference between C-like
variables and Python bindings be important enough to no longer
use that word.

Use the word that you want, I don't give a damn. I can't help if you're
clueless enough to understand why I wanted to emphasis the difference.
Stating that one language has no variables, looks a poor choice of
words to me for saying that variables in C and python don't behave
entirely the same.
>>>>>>>What you really have is (somewhat simplified, of course) a dict with
>>>names as keys and objects references (think of 'smart' pointers) as
>>>values.
>>
>>
>>That is just an implementation issue.

yes, your favourite argument ever.


What is your point? That it is my favourite argument ever doesn't
make it wrong or invalid.

Does it occurs to you that most languages are designed with specific
requirements in mind ? (well, for those that are designed at least). And
that a good part of these requirements are about or closely related to
implementation issues ?
Yes and it is irrelevant. That a number of requirements don't leave
the implementor much choice, doesn't contradict that specific details
are implementation details, and that you can't argue whether or
not python has variables based on details of a specific implementation.
>If you have an issue with it, bring
your arguments. The fact is that if you don't want to use the
word variable,

I use it everyday.
But you did write that python didn't have variables.
>you can't rely on current implementation details,
because implementation details can change without the language
changing.

Yeah, great. Now you're done with theory, let's get pragmatic.
That doesn't change a thing. What one can do with the language
is defined by the language reference. Not by a specific implementation.
>>>>If someone would wish to extend
python with a type system,

In case you don't know, it already has one.


I'll be more clearer: If someone wants to extend python with
a kind of static typing,

I dont.
So what? This is not about *you*. So what you want or not is
totally irrelevant. You just made a smart ass remark and cut
away the point being made. That the second time I see you
responding like that. Don't you have real arguments?
>>>>>>The name is just a way for refering to a memory space which
>>will hold something.
>
>The name is a symbolic name for a memory address in which bits will be
>stored (and the type information is used to know how to interpret the
>bits at this address - I leave storage class problems aside). There's a
>direct translation from symbolic name to memory address to bits.
That doesn't need to be. A C-implementation could use directories.

"could", yes. But I'm not talking about language grammar.


Neither am I, I am talking about language semantics.
If a C-implementation could use directories, that means
that directories can be used to capture the C-semantics.

I don't care, and I really doubt anyone working on a C implementation
cares much. C has been designed to be as simple as possible to
implement, as close to the hardware as possible, and as fast as
possible. It has been designed for system programming - actually to make
Unix portable to other architectures. It's very obvious for anyone with
a not too limited understanding that C design is very closely related to
these goals.
Again irrelevant. That these are the goals of those who design(ed) C,
doesn't mean other implementations are impossible. C interpreters
do exist. And such an interpreter can use directories for managing
his namespaces.
>So whether the implementation uses direct translation
from name to memory to bits or uses directories, it
doesn't change one bit what one can do with a variable
in the language.

fine.
>Besides, you don't seem to have a problem talking about
Lisp-variables, and Lisp-variables don't have such
a direct translation from symbolic name to memory
address either. So this specific detail of most C-implementations
seems mostly irrelevant to me.

The fact that it seems irrelevant to you seems totally irrelevant to me.
Good night.
But that you don't present much arguments for your case, seems
very relevant to me.

--
Antoon Pardon
Jul 28 '06 #48

P: n/a
On 2006-07-28, Dennis Lee Bieber <wl*****@ix.netcom.comwrote:
On 27 Jul 2006 18:09:37 GMT, Antoon Pardon <ap*****@forel.vub.ac.be>
declaimed the following in comp.lang.python:
>>
It is irrelevant because the word "variable" is used in a lot of
different languages. A lot of them with behaviour closer to python
than to C. The difference between C variables and Python bindings
is only relevant if it can give you an argument for why we shouldn't
use "variable" when discussing python.
Typically, "variable" implies a data storage location that can take
on different values. Emphasis on "location" -- the name is fixed to a
memory location whose contents can be varied.
That is not true. It may be the case in a number of languages but
my experience with lisp and smalltalk, though rather limited,
says that no such memory location is implied with the word "variable"
in those languages and AFAIK they don't have a problem with the
word "variable" either.
In Python, the closest
would be a mutable object.
Python names are not fixed to a location.
Neither are smalltalk and lisp variables. Neither are C-variables
local to functions.
One can actually delete
the name at runtime and NOT have the object deleted.
How important is this? Should we remove the del statement from
python would it make such a big difference that you would then
think the term "variable" was more appropiate?
>I'll be more clearer: If someone wants to extend python with
a kind of static typing, where you could limit names binding only
to objects of a certain number of classes, it wouldn't essentially
change what could be done with names in python, but the names would now
hold type information too. So whether a name carries type information
or not, has little relevance to whether the term "variable" is appropiate
or not.
And what happens if you do a "del name1" followed by some binding to
name1? Will the restriction of name1 to a limited class of objects be an
executable statement (a la def)? If so, how would you handle:

dec name1(object1)

def x():
# do something using global scoped name1
#expecting an object1 inference?

del name1
dec name1(object2)

x() #invoke x when name1 has object2 aspects

If you forbid the "del name1", you have just violated your wouldn't
essentially change" statement. If you permit del and an executable
typing statement, you've just lost your "static typing"
1) I think that is unimportant. Maybe "static typing" was not the right
wording. One argument against the use of the term "variable" in python
was that unlike C, there was no type information associated with a name.
My hypothetical extention to Python would be a very python-like language
where type information was associated with a name. Now if you want to
call this specific type extention, static or something else is IMO
not important. The point is that what one can do with variable is
hardly affected by this characteristic of names being associated
with type information or not.

Beside, Lisp and smalltalk variables don't have type information
associated with names either.

--
Antoon Pardon
Jul 28 '06 #49

P: n/a
On 2006-07-28, Dennis Lee Bieber <wl*****@ix.netcom.comwrote:
Hmmm, I've not followed the PEPs -- has any thought been given to
unifying class/instance and dictionary notation so that

a['b']
and
a.b
If that is what you want, you could use the following class:

class Unified(object):
def __init__(__, **kwargs):
for key,value in kwargs.items():
setattr(__, key, value)

def __getitem__(self, key):
return getattr(self, key)

def __setitem__(self, key, value):
setattr(self, key, value)
Jul 28 '06 #50

78 Replies

This discussion thread is closed

Replies have been disabled for this discussion.