On Mon, 12 Jul 2010 20:28:49 +0200, Alf P. Steinbach /Usenet wrote: > As I see it it doesn't matter whether the implementation is CPython call > frame slots or that mechanism called something else or a different > mechanism called the same or a different mechanism called something > different; what IMO matters is same semantics, that any assignment to a > variable within a routine serves as a compile time declaration, creating > that local variable in advance, unless, with Python 3.x., that name has > been declared as a 'global' or 'nonlocal'. > > So, this is a possible point of disagreement. > > I say the semantics of local variable creation are part of the language > definition, but I get the /impression/ that maybe you think it's > CPython-specific, that e.g. > > def foo(): > x > x = 0 > > might not raise an unassigned variable exception with some conforming > Python implementation, i.e. different effect for same code with > different implementations, that this is at least /unspecified behavior/ > in Python?
Almost. I believe that "any assignment to a variable within a routine serves as a compile time declaration" is a promise of the language, but what an implementation does in response to that declaration is unspecified. So long as foo() raises NameError, or a subclass of it, it will be a conforming Python implementation. That's what Python 1.5 does, and I think if some competing implementation targeted 1.5 we'd still be happy to call it Python. (Although we might wonder about the author's sanity...) Implementations are free to subclass NameError, as CPython does with UnboundLocalError, but mustn't raise a completely unrelated error, or no error at all. E.g. I don't think it would be acceptable to implicitly create new names and bind them to some arbitrary default value. E.g. an implementation might do something like this: * when parsing the function, prior to compiling the byte-code, tag every name with a sigil representing whether it is local or non-local; * compile a single byte-code for name lookup; * when executing that instruction, if the name is tagged as a local, search only the local namespace, otherwise search the nonlocal, global and builtin namespaces; * when displaying names to the user (say, in tracebacks) suppress the sigil. Under this implementation, no variable actually exists until it is assigned to. This is equivalent to shifting the decision to use LOAD_FAST or LOAD_GLOBAL to runtime rather than compile time, so it would probably hurt performance rather than increase it, but it would still be a conforming implementation. But of course I'm not Guido, and he has the final word on what counts as acceptable behaviour. -- Steven -- http://mail.python.org/mailman/listinfo/python-list