The Python walrus operator (:=) is listed in the documentation as an operator, but not as a delimiter like the rest of the assignment operators (e.g. +=). Why then is the walrus operation not also a delimiter?
Why is the walrus operator not a delimiter?
264 Views Asked by llll0 AtThere are 2 best solutions below
On
The main reasoning for why its not allowed is to avoid ambiguity in code. More exceptional cases from PEP 572 – Assignment Expressions
Unparenthesized assignment expressions are prohibited at the top level of an expression statement. Example:
y := f(x) # INVALID (y := f(x)) # Valid, though not recommendedThis rule is included to simplify the choice for the user between an assignment statement and an assignment expression – there is no syntactic position where both are valid.
Unparenthesized assignment expressions are prohibited at the top level of the right hand side of an assignment statement. Example:
y0 = y1 := f(x) # INVALID y0 = (y1 := f(x)) # Valid, though discouragedAgain, 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. Example:
foo(x = y := f(x)) # INVALID foo(x=(y := f(x))) # Valid, though probably confusingThis rule is included to disallow excessively confusing code, and because parsing keyword arguments is complex enough already.
Unparenthesized assignment expressions are prohibited at the top level of a function default value. Example:
def foo(answer = p := 42): # INVALID ... def foo(answer=(p := 42)): # Valid, though not great style ...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), and also to echo the similar prohibition in calls (the previous bullet).
Unparenthesized assignment expressions are prohibited as annotations for arguments, return values and assignments. Example:
def foo(answer: p := 42 = 5): # INVALID ... def foo(answer: (p := 42) = 5): # Valid, but probably never useful ...The reasoning here is similar to the two previous cases; this ungrouped assortment of symbols and operators composed of : and = is hard to read correctly.
Unparenthesized assignment expressions are prohibited in lambda functions. Example:
(lambda: x := 1) # INVALID lambda: (x := 1) # Valid, but unlikely to be useful (x := lambda: 1) # Valid lambda line: (m := re.match(pattern, line)) and m.group(1) # ValidThis allows lambda to always bind less tightly than :=; having a name binding at the top level inside a lambda function is unlikely to be of value, as there is no way to make use of it. In cases where the name will be used more than once, the expression is likely to need parenthesizing anyway, so this prohibition will rarely affect code.
Assignment expressions inside of f-strings require parentheses. Example:
>>> f'{(x:=10)}' # Valid, uses assignment expression '10' >>> x = 10 >>> f'{x:=10}' # Valid, passes '=10' to formatter ' 10'This shows that what looks like an assignment operator in an f-string is not always an assignment operator. The f-string parser uses : to indicate formatting options. To preserve backwards compatibility, assignment operator usage inside of f-strings must be parenthesized. As noted above, this usage of the assignment operator is not recommended.
You write “the rest of the assignment operators”, but there is only one assignment operator in Python, and that’s the walrus operator! The other assignment... thingies are delimiters in an assignment statement.