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 -- http://mail.python.org/mailman/listinfo/python-list