
On Friday 24 October 2003 23:32, Guido van Rossum wrote: ...
or at run-time) always goes from inner scope to outer. While you and I see nested functions as small amounts of closely-knit code, some people will go overboard and write functions of hundred lines long containing dozens of inner functions, which may be categorized into
This doesn't look like a legitimate use case to me; i.e., I see no need to distort the language if the benefit goes to such "way overboard" uses. I think they will have serious maintainability problems anyway. Fortunately, I don't think of placing the "indication to the compiler" as close to the assignment-to-outer-variable as a distortion;-)
Anyway, I hope you'll have a look at my reasons for why the compiler needs to know about rebinding variables in outer scopes from inside an inner scope.
Sure! I do understand this. What I don't understand is why, syntactically, the reserved word that indicates this to the compiler should have to be a "statement that does nothing" -- the ONLY "declaration" in the language -- rather than e.g. an _operator_ which specifically flags such uses. Assume for the sake of argument that we could make 'scope' a reserved word. Now, what are the tradeoffs of using a "declaration" scope x in outer which makes all rebidings of x act in the scope of containing function outer (including 'def x():', 'class x:', 'import x', ...); versus an "operator" that must be used to indicate "which x" when specifically assigning it (no "side effect rebinding" via def &c allowed -- I think it helps the reader of code a LOT to require specific assignment!), e.g. scope(outer).x = 23 Don't think of scope as a built-in function, but as a keyword in either case (and we could surely have other syntax for the "scope operator", e.g. "(x in outer scope) = 23" or whatever, as long as it's RIGHT THERE where x is being assigned). So the compiler can catch on to the info just as effectively. The tradeoffs are: -- we can keep thinking of Python as declaration-free and by gradually deprecating the global statement make it more so -- the reader of code KNOWS what's being assigned to without having to scroll up "hundreds of lines" looking for possible declarations -- assignment to nonlocals is made less casually convenient by just the right amount to ensure it won't be overused -- no casual rebinding of nonlocals via def, class, import -- once we solve the general problem of allowing non-bare-names as iteration variables in 'for', nonlocals benefit from that resolution automatically, since nonlocals are never assigned-to as bare-names I see this as the pluses. The minus is, we need a new keyword; but I think we do, because stretching 'global' to mean something that ISN'T global in any sense is such a hack. Cutting both ways is the fact that this allows using the same name from more than one scope (since each use is explicitly qualified as coming from a specific scope). That's irrelevant for small compact uses of nesting, but it may be seen as offering aid and succour to those wanting to "go overboard" as you detail earlier (bad); OTOH, if I ever need to maintain such "overboard" code written by others, and refactoring it is not feasible right now, it may be helpful. In any case, the confusion is reduced by having the explicit qualification on assignment. Similarly for _accesses_ rather than rebindings -- access to the barename will keep using the same rules as today, of course, but I think the same syntax that MUST be used to assign nonlocals should also be optionally usable to access them -- not important either way in small compact functions, but more regular and offering a way to make code non-ambiguous in large ones. I don't see having two ways to access a name -- barename x or qualified scope(foo).x -- as a problem, just like today from inside a method we may access a classvariable as "self.x" OR "self.__class__.x" indifferently -- the second form is needed for rebinding and may be chosen for clarity in some cases where the first simpler ("barer") one would suffice. Alex