Need help with Python scoping rules

John Posner jjposner at optimum.net
Tue Aug 25 17:56:51 EDT 2009


Stephen Hansen said:
>
>
>     But http://docs.python.org/tutorial/classes.html says, in Section
>     9.3 "A First Look at Classes":
>
>     When a class definition is entered, a new namespace is created,
>     and used as the local scope — thus, all assignments to local variables
>     go into this new namespace. In particular, function definitions bind
>     the name of the new function here.
>
> [snip] 
>
>
>     (BTW, Diez, your toy example is another demonstration that there
>     *is* a class-scope-lookup: the "def" statement binds the name
>     "fact" in the class scope, and the assignment statement looks up
>     the name "fact" in that scope.)
>
>
> This sounds like a fundamental confusion -- a namespace is not 
> equivalent to a scope, really, I think.

My apologies if I was being too loose with the terms "namespace" and 
"scope". I was trying to use Diez's terminology (e.g. 
"class-scope-lookup"). But I think you agree with me in *almost* 
everything you say below.

>
> The def statement creates a function object, and assigns it to the 
> given name, in its /local scope/ which is the class's namespace -- but 
> that is not a new scope. Its just, during class creation, the local scope.
>
> When you enter a class definition, a new namespace is created, and 
> that is used as the local scope during the class's definition. Under 
> "class Foo", the local scope is this class's namespace-- and the 
> global scope is the module's namespace. Any lookup operation checks 
> first in the local scope, then in the global scope... 
>
> When the "def fact(...)" is executed (note that class bodies are 
> executed on load, function bodies aren't), a new namespace is created 
> as well-- the function's namespace-- and its used as the local scope. 
> During execution of the code, it looks up in the local scope first-- 
> and then it looks up in the global scope if it doesn't find anything. 
> There /is/ no class-lookup-scope... but there IS a class namespace.
>
> There's just those two scopes: but the namespace bound to those scopes 
> changes as you enter different parts of the code. 
>
> For a long time that's all there was, just the local and global scope: 
> to access any other namespace required you to explicitly address it. 
> The class namespace remains accessible only via explicit addressing, 
> but PEP 227 in Python 2.1/2.2 introduced static nested scopes. But 
> that applies only to enclosing functions: embedding one function into 
> another.
>
> You can only call recursive functions if the function is able to refer 
> to itself according to the same lookup rules: is the function's name 
> in the local scope? No it's not... is it in the global scope? No? Then 
> it can't call itself recursively... well, unless its a method, and it 
> addresses itself specifically-- with "self.".

All of the above is consistent with my previous post.

>
> The OP's probably is that during the execution of the class body, the 
> class doesn't exist... so the 'def fact' -can't- use Classname.fact to 
> address itself explicitly, and within fact the locals don't contain a 
> reference to the function itself, and its globals don't either. You 
> just can't do that.

Here's where we disagree, and I'm sticking to my guns. The fact that the 
class definition has not been completely processed is irrelevant. The 
OP's problem was attempting to implement a recursive function. A 
non-recursive implementation of fact() works fine:

class ThisWorks(object):
    def fact(n):
        answer = 1
        i = 1
        while i <= n:
            answer *= i
            i += 1
        return answer

    clsvar = fact(4)

print ThisWorks.clsvar  # output: 24


> The right way, IMHO, is to move 'fact' up and out of the class ...

We're back to agreement on this point!

-John




More information about the Python-list mailing list