Python's scope rules

Tim Peters tim.one at home.com
Wed Dec 20 05:45:41 EST 2000


[Brian Elmegaard]
> I am not a computer scientist, just an engineer knowing how to
> program in Fortran, Pascal,... So I after reading some of the
> python material on the web, I decided to give it a try and is
> now using the language some, finding it fun and easy.

It will stay that way too -- provided you don't pay too much attention to
computer scientists <wink>.

> On usenet I have now learned from skilled scientists, that Python
> has some deficiencies regarding scope rules, and I am not capable
> of telling them why it has not (or that it has).

Some of the arguments pro and con are summarized in PEP (Python Enhancement
Proposal) 227, at

    http://python.sourceforge.net/peps/pep-0227.html

Python's current scheme is very usable in practice; some people will never
like it, though, because it's not exactly like anything else.

> In Aaron Watters 'The wwww of python' I have read that Python uses
> lexical scoping with a convenient modularity. But, other people
> tell me it does not.  Some say it uses dynamic scoping, some say
> it uses it own special 'local-global-builtin' scope. What is right?

The rules are detailed in the language reference manual's section 4.1 ("Code
blocks, execution frames, and namespaces"), at

    http://www.python.org/doc/current/ref/execframes.html

The fundamental rule is that a name is local to a block if and only if it
(a) is assigned to somewhere in the block, and (b) does not appear in a
"global" statement within the block.  Note that this applies to *all* names!
In particular, there's nothing special about function, class or module names
as opposed to variable names.

It's proper to call this lexical scoping because the local vs non-local
decision is made wholly at compile-time; but most people who use terms like
"lexical scoping" have backgrounds in languages where lexical scopes nest
arbitrarily deep (the subject of PEP 227), and are offended that Python is
simpler than that <wink>.

> The above mainly is a theoretical question. A more practical
> example which I agree seems a bit odd is:

I'll explain this in detail.  That may make it *look* complicated.  But it's
not:  the detail is needed in order to bring out how uniform it is.  Things
are going on that you don't realize at first.  There is in fact no reason
you ever need to realize some of these, but if you're going to plumb the
depths of name resolution in Python then you need to know them:

> Python 1.5.2 (#1, Mar  9 2000, 17:40:34)  [GCC 2.95.2 19991024
> (release)] on hp-uxB
> Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
> >>> x=24

x is assigned to here, so x is local to *its* code block.  Its code block
happens to be the module whose name is "__main__", which module Python
invented for you because you're in an interactive session.  Code always
executes in the context of *some* module.  Modules have the peculiar
property that their local and global namespaces are the same.

> >>> def foo():

Something you weren't expecting:  "def" is an executable statement in
Python, and also acts like an assignment.  The appearance of "def foo()"--
just like "x=24" --makes foo a name local to module __main__ too.  A def
statement also introduces a new code block.

> ...     y=2
> ...

y is assigned to within foo's code block, so y is a name local to foo.

> ...     print x+y

x is not assigned to within foo's code block, so x is not local to foo.  It
will be looked up in foo's global namespace instead (== the local namespace
of module __main__).

> >>> def bar():

Introduces "bar" as a name local to __main__, and starts a new code block.

> ...     x=11

x is assigned to within bar's code block, so this x is local to bar (and has
nothing whatsoever to do with the name x that's local to __main__).

> ...     foo()
> ...

Note!  The name "foo" is not assigned to within bar's code block, so the
name foo is not local to bar.  It will be looked up in bar's global
namespace instead (== the local namespace of module __main__).  This is
*exactly* the same rule that caused us to look up "x" in the global
namespace within function "foo":  there's nothing special about function
names.  All names get resolved by the same little set of rules.

> >>> bar()

bar is local to __main__, so gets resolved in __main__'s local namespace.

> 26
> >>>

> Well, I can live with it.

More easily than you may think, too.

> In Fortran I would always put all the variables to be
> passed in the parameter list.

Or in common blocks.  While in Pascal, you would declare names local to a
function within that function.  But Python has no declarations (ignore
"global" for now), and needs *some* rule to determine what is and isn't
local.  The "local if and only if bound somewhere in the block" rule usually
works out just right by magic.  The consequence that may be unique to Python
is that, from within a function contained in a module, it's impossible to
assign directly to a module-local name unless that name is listed in a
"global" statement within the function (indeed, that's why the "global"
statement exists).  I think that's a Good Thing:  mucking with global
variables makes code hard to understand, so if you *have* to go changing the
bindings of globals, it's Good that the language makes you say something
extra to point that out.

> Other people say that Fortran is not easy, and this example shows how
> stupid python is. It does?

I suspect you've got Fortran77 in mind -- and F77 also has simple rules.

> Hopefully not, but probably, this is a faq, but I have not been
> able to find anything on the matter.

It's hard to find.  Guido (van Rossum, Python's father) has written that
Python's "2-level scope nesting" was in part a reaction against the abuses
of deep lexical nesting common in large Pascal programs of the time.  I
didn't like Python's scope rules when I first saw the language (I didn't
think "simple", I thought "simple-minded"!), but that argument persuaded me
to give it a chance -- since I had also been on the receiving end of other
peoples' insanely nested Pascal monsters.  Within a year I learned how to
make good use of modules and classes in Python to manage names, and Python's
scope rules never bothered me again.  I think they're great!  Unfortunately,
they're not what anyone coming from other languages expect, and that's why
PEP 227 is being seriously considered for Python 2.1.

it's-all-lambda's-fault-but-that-tale-of-woe-is-for-another-day-ly
    y'rs  - tim





More information about the Python-list mailing list