This PEP adds a new assignment expression to the Python language to make it possible to assign the result of an expression in almost any place. The new expression will allow the assignment of the result of an expression at first use (in a comparison for example).
Motivation and SummaryIssue1714448 “if something as x:” [1] describes a feature to allow assignment of the result of an expression in an if statement to a name. It supposed that the as
syntax could be borrowed for this purpose. Many times it is not the expression itself that is interesting, rather one of the terms that make up the expression. To be clear, something like this:
if (f_result() == [1, 2, 3]) as res:
seems awfully limited, when this:
if (f_result() as res) == [1, 2, 3]:
is probably the desired result.
Use CasesSee the Examples section near the end.
SpecificationA new expression is proposed with the (nominal) syntax:
This single expression does the following:
EXPR
, an arbitrary expression;VAR
, a single assignment target; andEXPR
on the Top of Stack (TOS)Here ->
or (RARROW
) has been used to illustrate the concept that the result of EXPR
is assigned to VAR
.
The translation of the proposed syntax is:
The assignment target can be either an attribute, a subscript or name:
f() -> name[0] # where 'name' exists previously. f() -> name.attr # again 'name' exists prior to this expression. f() -> name
This expression should be available anywhere that an expression is currently accepted.
All exceptions that are currently raised during invalid assignments will continue to be raised when using the assignment expression. For example, a NameError
will be raised when in example 1 and 2 above if name
is not previously defined, or an IndexError
if index 0 was out of range.
The following two examples were chosen after a brief search through the standard library, specifically both are from ast.py which happened to be open at the time of the search.
Original:
def walk(node): from collections import deque todo = deque([node]) while todo: node = todo.popleft() todo.extend(iter_child_nodes(node)) yield node
Using assignment expression:
def walk(node): from collections import deque todo = deque([node]) while todo: todo.extend(iter_child_nodes(todo.popleft() -> node)) yield node
Original:
def get_docstring(node, clean=True): if not isinstance(node, (FunctionDef, ClassDef, Module)): raise TypeError("%r can't have docstrings" % node.__class__.__name__) if node.body and isinstance(node.body[0], Expr) and \ isinstance(node.body[0].value, Str): if clean: import inspect return inspect.cleandoc(node.body[0].value.s) return node.body[0].value.s
Using assignment expression:
def get_docstring(node, clean=True): if not isinstance(node, (FunctionDef, ClassDef, Module)): raise TypeError("%r can't have docstrings" % node.__class__.__name__) if node.body -> body and isinstance(body[0] -> elem, Expr) and \ isinstance(elem.value -> value, Str): if clean: import inspect return inspect.cleandoc(value.s) return value.sExamples
The examples shown below highlight some of the desirable features of the assignment expression, and some of the possible corner cases.
def expensive(): import time; time.sleep(1) return 'spam' if expensive() -> res in ('spam', 'eggs'): dosomething(res)
while len(expensive() -> res) == 4: dosomething(res)
for ch in expensive() -> res: sell_on_internet(res)
for ch -> please_dont in expensive(): pass # who would want to do this? Not I.
This document has been placed in the public domain.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4