On 12/06/10 11:18, Demur Rumed wrote:
I believe it would be simpler to learn that variables are _only_ local if bound with the assignment operator. I view the augmented assignment operators as different beasts. This patch doesn't quite meet its goals in that respect. I'd like to further the locality of a variable to "A variable is local if, and only if, it is first referenced as the left hand side of an assignment on all code paths." This patch fails to set that rule
The only thing even *remotely* on the table here is to take augmented assignment out of the list of statements that will create a new local variable. For 3.x, that list is currently: - assignment (i.e. '=') - augmented assignment (i.e. '+=', '*=', etc) - function/generator definitions (i.e. def)* - class definitions - for loops - try/except statements - import statements - with statements *Unlike other statements in this list, def statements can affect two different scopes. The defined name becomes a local in the scope containing the statement, while the names of any declared parameters become local inside the statement's own scope. The compiler identifies local variables via static analysis of the function as a whole to see if they are used as name binding targets in any of the above statements *anywhere* in the function. We are *not* going to change that, not just because doing anything else would be far to error-prone, but also because any other interpretation would make compilation far too difficult. For example, consider the following example: def f(x): if randint(2): a = [5] return a[x] # Emit code for global or local lookup? The compiler has to choose to emit a global or local lookup opcode at compile time - it doesn't have the luxury of knowing whether or not the name binding statement will actually be executed at runtime, so it ignores any conditional execution when deciding whether or not a name is bound locally. UnboundLocalError then covers all cases where you attempt to use a local variable name before you have bound it to something. Now, as to the reason we can even consider taking augmented assignment out of the list above: of the current name binding statements, it is the *only* one which requires that a referenced name already be bound using one of the *other* statements in the list. If augmented assignment is currently used in a function *without* raising UnboundLocalError at runtime, then that can only be because the target has been bound by other means, either in the current scope, or else in a different scope and then explicitly declared as coming from another scope via a global or nonlocal statement. So, without breaking existing code (that wasn't already broken), we could change the default scope for augmented assignment from "always use the local scope" to be: - if a name is declared local by other means, treat it is local - it the name exists in a surrounding scope, treat it as nonlocal - otherwise treat it as global That would almost certainly be more useful than the current behaviour. The question is whether it is *sufficiently* useful to justify the effort in updating the documentation and implementing this not just for CPython, but for other VMs such as Jython, IronPython and PyPy. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------