Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 379 – Adding an Assignment Expression

Author:
Jervis Whitley <jervisau at gmail.com>
Status:
Withdrawn
Type:
Standards Track
Created:
14-Mar-2009
Python-Version:
2.7, 3.2
Post-History:


Table of Contents

Abstract

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 Summary

Issue1714448 “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 theassyntax 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])asres:

seems awfully limited, when this:

if(f_result()asres)==[1,2,3]:

is probably the desired result.

Use Cases

See the Examples section near the end.

Specification

A new expression is proposed with the (nominal) syntax:

EXPR->VAR

This single expression does the following:

  • Evaluate the value ofEXPR,an arbitrary expression;
  • Assign the result toVAR,a single assignment target; and
  • Leave the result ofEXPRon the Top of Stack (TOS)

Here->or (RARROW) has been used to illustrate the concept that the result ofEXPRis assigned toVAR.

The translation of the proposed syntax is:

VAR=(EXPR)
(EXPR)

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, aNameErrorwill be raised when in example 1 and 2 above ifnameis not previously defined, or an IndexErrorif index 0 was out of range.

Examples from the Standard Library

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:

defwalk(node):
fromcollectionsimportdeque
todo=deque([node])
whiletodo:
node=todo.popleft()
todo.extend(iter_child_nodes(node))
yieldnode

Using assignment expression:

defwalk(node):
fromcollectionsimportdeque
todo=deque([node])
whiletodo:
todo.extend(iter_child_nodes(todo.popleft()->node))
yieldnode

Original:

defget_docstring(node,clean=True):
ifnotisinstance(node,(FunctionDef,ClassDef,Module)):
raiseTypeError("%rcan't have docstrings "
%node.__class__.__name__)
ifnode.bodyandisinstance(node.body[0],Expr)and\
isinstance(node.body[0].value,Str):
ifclean:
importinspect
returninspect.cleandoc(node.body[0].value.s)
returnnode.body[0].value.s

Using assignment expression:

defget_docstring(node,clean=True):
ifnotisinstance(node,(FunctionDef,ClassDef,Module)):
raiseTypeError("%rcan't have docstrings "
%node.__class__.__name__)
ifnode.body->bodyandisinstance(body[0]->elem,Expr)and\
isinstance(elem.value->value,Str):
ifclean:
importinspect
returninspect.cleandoc(value.s)
returnvalue.s

Examples

The examples shown below highlight some of the desirable features of the assignment expression, and some of the possible corner cases.

  1. Assignment in an if statement for use later:
    defexpensive():
    importtime;time.sleep(1)
    return'spam'
    
    ifexpensive()->resin('spam','eggs'):
    dosomething(res)
    
  2. Assignment in a while loop clause:
    whilelen(expensive()->res)==4:
    dosomething(res)
    
  3. Keep the iterator object from the for loop:
    forchinexpensive()->res:
    sell_on_internet(res)
    
  4. Corner case:
    forch->please_dontinexpensive():
    pass
    # who would want to do this? Not I.
    

References


Source:https://github.com/python/peps/blob/main/peps/pep-0379.rst

Last modified:2023-09-09 17:39:29 GMT