[SOLVED] Why is the walrus operator not a delimiter?

Issue

This Content is from Stack Overflow. Question asked by llll0

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?



Solution

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 recommended

This 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 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. 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.

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) # Valid

This 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.


This Question was asked in StackOverflow by llll0 and Answered by flakes It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?