[Zope] Scoping question (Python scripts)

Martijn Pieters mj@digicool.com
Mon, 9 Apr 2001 11:39:30 +0200


On Mon, Apr 09, 2001 at 12:38:55AM -0700, Kirby Urner wrote:
> I'm unclear on how scoping is handled in Python scripts.
> 
> =====
> ## parameters = name
> print "Hello %s" % name
> return printed
> =====
> 
> works as a script but:
> 
> =====
> ## parameters = name
> print function()
> print "Hello %s" % name
> return printed
> 
> def function():
>    return "Goodbye"
> =====
> 
> does not -- because 'function' is not found.  However:
> 
> =====
> ## parameters = name
> def function():
>    return "Goodbye"
> 
> # Main
> print function()
> print "Hello %s" % name
> return printed
> 
> =====
> 
> is OK, as 'function' is defined above the main stuff.  However
> I can't get 'function' to see another function e.g.:
> 
> 
> =====
> ## parameters = name
> 
> def add2(a):
>    return a+2
> 
> def function():
>    n = add2(3)
>    return "Goodbye"
> 
> # Main
> print function()
> print "Hello %s" % name
> return printed
> 
> =====
> 
> 'add2' won't be found, I guess because it's "two levels deep" (??).
> However, it'll work if I make 'add2' internal to 'function'...
> 
> =====
> ## parameters = name
> 
> def function():
>    def add2(a):
>       return a+2
> 
>    n = add2(3)
>    return "Goodbye"
> 
> # Main
> print function()
> print "Hello %s" % name
> return printed
> 
> =====
> 
> So what are the rules here?  I'm used to Python modules with one 
> shared scope for all top-level function defs, no matter what level
> they're called from.  Why can't 'add2' be defined at the same 
> level as 'function' (above), or is there syntax to make this work
> (I've been trying stuff like script.add2(3) or context.add2(3) 
> but that doesn't help).

This sounds like your typical Python nested namespaces problem, which is
solved in Python 2.1 in an optional __future__ module, and standard fare
in Python 2.2.

A python Script is a function in itself, so it's namespace isn't the
global module space you are expecting. Normally, you would indeed expect
function() and add2() to be visible throughout your script, as they have
been defined at the module level.

However, a Python Script isn't defined at the module level; it is defined
as a function within a module. you should mentally indent the whole code
and add 'function <id of PS here>(<paramater list here>):' before it. So,
here only the local scole rules apply: only names that have been declared
before you are visible, and you get a new local namespace when calling a
function.

Python 2.1 solves this problem by introducing nested scopes. I assume that
because Zope 2.4 will probably require Python 2.1, the problem will
disappear (if Python Scripts do a 'from __future__ import nested_scopes).
For now however, you'll have to live with this problem, or see if you can
manipulate globals() in Python Scripts (not sure if you can).

A good overview of what nested scopes are about, see:

  http://www.amk.ca/python/2.1/index.html#SECTION000300000000000000000

The original PEP is at:

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

And finally, the official documentation can be found at:

  http://python.sourceforge.net/devel-docs/ref/nested-scopes.html

-- 
Martijn Pieters
| Software Engineer  mailto:mj@digicool.com
| Digital Creations  http://www.digicool.com/
| Creators of Zope   http://www.zope.org/
---------------------------------------------