[Python-Dev] assignment expressions: an alternative proposal

Yury Selivanov yselivanov.ml at gmail.com
Tue Apr 24 09:38:33 EDT 2018


I propose to use the following syntax for assignment expressions:

    ( NAME = expr )

I know that it was proposed before and this idea was rejected, because
accidentally using '=' in place of '==' is a pain point in
C/C++/JavaScript.

That said, I believe we can still use this syntax as long as we impose
the following three restrictions on it:

1. Only NAME token is allowed as a single target.

2. Parenthesis are required.

3. Most importantly: it is *not* allowed to mask names in the current
local scope.


Let's see how each restriction affects the syntax in detail:

(1) NAME tokens only:

  if (a[1] = value)    # SyntaxError
  if (a.attr = value)  # SyntaxError

(2) Required parens disambiguate the new syntax from keyword-arguments
and prevent using '=' in place of '==':

   if a = value    # SyntaxError
   if expr and a = value    # SyntaxError

(3) No masking of existing names in local scope makes using '=' in
place of '==' by mistake even less probable:

   flag = get_flag()
   ...
   if (flag = 'win')    # SyntaxError

   # or

   def foo(value):
      if (value = 1)   # SyntaxError

   # or

   py> (c = 1) and (c = 2)   # SyntaxError

   # etc


The following code snippets are perfectly valid though:

py> a = (b = (c = 3))
py> a, b, c
(3, 3, 3)

  # and

py> f = lambda x: x * 10
py> [[(y = f(x)), x/y] for x in range(1,5)]
[[10, 0.1], [20, 0.1], [30, 0.1], [40, 0.1]]

  # and

  def read():
      while (command = input("> ")) != "quit":
         print('you entered', command)

  # and

py> if (match = re.search(r'wor\w+', 'hello world')):
py.     print(match)
<re.Match object; span=(6, 11), match='world'>

  # and

 if (diff = x - x_base) and (g = gcd(diff, n)) > 1:
     return g


Enabling '=' for assignment expressions introduces a limited form of
the more general assignment statement. It is designed to be useful in
expressions and is deliberately simple to make it hard for users to
shoot in the foot. The required Python grammar changes are simple and
unambiguous.

Although it is still possible to accidentally mask a global name or a
name from an outer scope, the risk of that is significantly lower than
masking a local name.  IDEs and linters can improve the usability
further by highlighting invalid or suspicious assignment expressions.

I believe that this syntax is the best of both worlds: it allows to
write succinct code just like PEP 572, but without introducing a new
':=' operator.

An implementation of this proposal is available here:
https://github.com/1st1/cpython/tree/assign.

If this idea is deemed viable I will write a PEP detailing the
grammar/compiler changes and syntax restrictions.

Thanks,
Yury


More information about the Python-Dev mailing list