Nested function scope problem

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Fri Jul 28 03:07:20 EDT 2006


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



More information about the Python-list mailing list