Nested function scope problem

Bruno Desthuilliers onurb at xiludom.gro
Tue Jul 25 12:18:20 EDT 2006


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 <gelists at 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 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list