diff --git a/pep-0572.rst b/pep-0572.rst index b9f58d6f6..3f46ee9e7 100644 --- a/pep-0572.rst +++ b/pep-0572.rst @@ -111,8 +111,6 @@ efficient rewrite would have been:: if match2: return match2.group(2) -(TODO: Include Guido's evidence, and do a more systematic search.) - Syntax and semantics ==================== @@ -144,50 +142,45 @@ There are a few places where assignment expressions are not allowed, in order to avoid ambiguities or user confusion: - Unparenthesized assignment expressions are prohibited at the top - level of an expression statement; for example, this is not allowed:: + level of an expression statement. Example:: y := f(x) # INVALID + (y := f(x)) # Valid, though not recommended This rule is included to simplify the choice for the user between an assignment statements and an assignment expression -- there is no syntactic position where both are valid. - Unparenthesized assignment expressions are prohibited at the top - level in the right hand side of an assignment statement; for - example, the following is not allowed:: + level of the right hand side of an assignment statement. Example:: y0 = y1 := f(x) # INVALID + y0 = (y1 := f(x)) # Valid, though discouraged Again, this rule is included to avoid two visually similar ways of saying the same thing. - Unparenthesized assignment expressions are prohibited for the value - of a keyword argument in a call; for example, this is disallowed:: + of a keyword argument in a call. Example:: foo(x = y := f(x)) # INVALID + foo(x=(y := f(x))) # Valid, though probably confusing This rule is included to disallow excessively confusing code, and because parsing keyword arguments is complex enough already. -- Assignment expressions (even parenthesized or occurring inside other - constructs) are prohibited in function default values. For example, - the following examples are all invalid, even though the expressions - for the default values are valid in other contexts:: +- Unparenthesized assignment expressions are prohibited at the top + level of a function default value. Example:: def foo(answer = p := 42): # INVALID ... - - def bar(answer = (p := 42)): # INVALID + def foo(answer=(p := 42)): # Valid, though not great style ... - def baz(callback = (lambda arg: p := arg)): # INVALID - ... - - This rule is included to avoid side effects in a position whose + This rule is included to discourage side effects in a position whose exact semantics are already confusing to many users (cf. the common - style recommendation against mutable default values). (TODO: Maybe - this should just be a style recommendation except for the - prohibition at the top level?) + style recommendation against mutable default values), and also to + echo the similar prohibition in calls (the previous bullet). Scope of the target ------------------- @@ -196,7 +189,8 @@ An assignment expression does not introduce a new scope. In most cases the scope in which the target will be bound is self-explanatory: it is the current scope. If this scope contains a ``nonlocal`` or ``global`` declaration for the target, the assignment expression -honors that. +honors that. A lambda (being an explicit, if anonymous, function +definition) counts as a scope for this purpose. There is one special case: an assignment expression occurring in a list, set or dict comprehension or in a generator expression (below @@ -231,12 +225,11 @@ comprehension, for example:: An exception to this special case applies when the target name is the same as a loop control variable for a comprehension containing it. -This is invalid. (This exception exists to rule out edge cases of the +This is invalid. This exception exists to rule out edge cases of the above scope rules as illustrated by ``[i := i+1 for i in range(5)]`` or ``[[(j := j) for i in range(5)] for j in range(5)]``. Note that -this exception also applies to ``[i := 0 for i, j in stuff]``.) - -TODO: prohibit [... for i in i := ...] +this exception also applies to ``[i := 0 for i, j in stuff]``, as well +as to cases like ``[i+1 for i in i := stuff]``. A further exception applies when an assignment expression occurrs in a comprehension whose containing scope is a class scope. If the rules @@ -254,7 +247,8 @@ variable defined in the class scope from a comprehension.) See Appendix B for some examples of how the rules for targets in comprehensions translate to equivalent code. -TODO: use a a subclass of SyntaxError for various prohibitions? +The two invalid cases listed above raise ``TargetScopeError``, a +subclass of ``SyntaxError`` (with the same signature). Relative precedence of ``:=`` -----------------------------