Need help with Python scoping rules
Diez B. Roggisch
deets at nospam.web.de
Tue Aug 25 12:14:26 EDT 2009
kj wrote:
>
>
>
> I have many years of programming experience, and a few languages,
> under my belt, but still Python scoping rules remain mysterious to
> me. (In fact, Python's scoping behavior is the main reason I gave
> up several earlier attempts to learn Python.)
>
> Here's a toy example illustrating what I mean. It's a simplification
> of a real-life coding situation, in which I need to initialize a
> "private" class variable by using a recursive helper function.
>
> class Demo(object):
> def fact(n):
> if n < 2:
> return 1
> else:
> return n * fact(n - 1)
>
> _classvar = fact(5)
>
> This code fails to compile, with the error "global name 'fact' not
> defined".
>
> Scanning the Python Language Reference page I see nothing that
> would suggest to me a discussion of Python's scoping rules, let
> alone anything that would help me solve the specific problem above.
> I'm sure it's in there, *somewhere*, but it's anyone's guess where.
>
> Likewise, my book, Beazley's "Python: Essential Reference" is of
> no help. I don't doubt that the answer to my question "is in there,
> *somewhere*", but finding it (without reading the book sequentially
> from page 1) is a tall order.
>
> All that's left is trial-and-error, the worst kind of programming.
> And still I can't find the right way to do this... I've tried
> every variant of this code that I can imagine, including decorating
> fact with @staticmethod or @classmethod, etc., etc. (In the latter
> case, I get cryptic errors saying that the staticmethod or classmethod
> object is not callable. Or something like that.)
Classes are not scopes.
So the above doesn't work because name resolution inside functions/methods
looks for local variables first, then for the *global* scope. There is no
class-scope-lookup.
If you want anything else, you need to qualify it with a full name,
Demo.fact. Which isn't working for your example because "Demo" isn't
available yet.
But if you insist on the above methodology, you can do this:
class Demo(object):
def fact(n):
def inner(n):
if n < 2:
return 1
else:
return n * inner(n - 1)
return inner(n)
_classvar = fact(5)
This makes inner a *local* variable, which is found.
Diez
More information about the Python-list
mailing list