Nested function scope problem

G

Gerhard Fiedler

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
 
A

Antoon Pardon

Guess where the term "binding" comes from.

I don't see how that is relevant.
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.
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.
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.
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.
"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.
 
A

Antoon Pardon

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.
 
G

Gerhard Fiedler

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
 
B

Bruno Desthuilliers

Antoon Pardon a écrit :
I don't see how that is relevant.

No ?
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 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.
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.
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...
I'll be more clearer: If someone wants to extend python with
a kind of static typing,

I dont.
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.
 
B

Bruno Desthuilliers

Gerhard Fiedler a écrit :
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 !-)
 
B

Bruno Desthuilliers

Gerhard Fiedler a écrit :
This makes a lot more sense now.



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...
 
B

Bruno Desthuilliers

Gerhard Fiedler a écrit :
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 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.
Traceback (most recent call last):
File said:
>>> 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
 
G

Gerhard Fiedler

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:

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
 
D

Dennis Lee Bieber

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. In Python, the closest
would be a mutable object.

Python names are not fixed to a location. One can actually delete
the name at runtime and NOT have the object deleted. This can not be
done in C/C++... Even if you run a free() on something, you still have
the named memory location that was used to point at the object.
Moreover, you have to explicitly indicate if you are modifying the
content of the named location, or the object referenced by the content
of a location.

free(x) is not the same as del x

The former recycles the memory that x referenced, but still leaves x
with the, now-invalid, contents. The latter actually deletes the name x
from the scope, but leaves whatever object x had been bound to -- the
object is only done-away-with if the reference count reaches 0 and the
garbage collector disposes of it.
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"
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
D

Dennis Lee Bieber

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

abc = [] #create some object with "abc" bound to it
import xyz as abc #rebind "abc" to the "xyz" module
# equivalent to
# import xyz
# abc = xyz
# del xyz


--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
B

Bruno Desthuilliers

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




Rephrased as:

Isn't being on the LHS (of an assignment) the only way to (re)bind a
variable?

<pedantic>
s/variable/name/
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:
Traceback (most recent call last):
File said:
>>> a = []
>>> a []
>>> id(a) 1078043820
>>> def a(): pass ....
>>> a
>>> id(a) 1078026956
>>> class a: pass ....
>>> a
>>> 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:
Traceback (most recent call last):
Traceback (most recent call last):
File said:
>>> [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 !-)
 
G

Gerhard Fiedler

Gerhard Fiedler a écrit :

<pedantic>
s/variable/name/
</pedantic>

Ok, I missed this one :)
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
 
D

Dennis Lee Bieber

wondered (this is slightly related) is whether it wouldn't be really good
to make the difference between mutable and immutable objects more obvious.
For the most part, a mutable object is one in which you can "go
inside" -- though tuples cross the boundary (you can "go inside" to
fetch an element, but you cant change the inside). And to "go inside"
typically requires a qualified name -- that is, a name with some sort of
accessor attached: a[1:3] (list), a['b'] (dict), a.c (object attribute).

a.c = d

is still a rebinding... But NOT of "a"; it rebinds the "c" that is
inside "a"




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

are equivalent?
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
A

Antoon Pardon

Antoon Pardon a écrit :

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.
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.
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.
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.
I use it everyday.

But you did write that python didn't have variables.
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.

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?
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.
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.
 
A

Antoon Pardon

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?
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.
 
A

Antoon Pardon

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)
 
G

Gerhard Fiedler

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.

Maybe this gets somewhere. Consider variable != constant. Python names are
variables in that what they refer to (what is associated with them through
a dict) can be changed, through various means (most commonly assignment).
They are also variables in that what they refer to (usually) can be
changed. Whether an assignment or some other command changes the reference
association or the referenced object is one of the confusing issues with
Python. But that doesn't make a variable less variable... :)

Gerhard
 
G

Gerhard Fiedler

For the most part, a mutable object is one in which you can "go inside"
-- though tuples cross the boundary (you can "go inside" to fetch an
element, but you cant change the inside).

It's the "for the most part" part that I was wondering about :)

So is this correct: It's mutable if you can "go inside", that is, it has an
accessor attached to the name. Unless it's a tuple, in which case it's
immutable even though it has accessors attached. Otherwise, it is
immutable.

Or said in another way: Everything is immutable, except that collections of
objects (classes, lists, etc) may provide means to rebind members, which
then can be considered means to change objects.

I seem to slowly wrap my mind around this... :)

Gerhard
 
D

Dennis Lee Bieber

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.
Python objects can exist without a "variable" bound to them...
Though typically such would soon be garbage collected <G>

Traditional languages are the other way around... If a variable
exists, it may exist with no object/value (ie, it is uninitialized -- a
big problem in C). Python names can not exist (and be used) without
being bound to some object (even None is a defined object). Attempting
to use a name that has not been bound gives you the "unbound local" type
problem.

Yes, some other languages do define special flag values so that they
can detect the usage of an uninitialized item... But the variable itself
exists regardless; you can not detach the object from the variable
(except by assigning something else to the variable).
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.
They don't behave the same...
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top