9

With Python 3.8 Assignment Expressions have been introduced, allowing to assign values in conditionals and lambdas as such:

if x := True:
    print(x)

However it appears this does not extends to attribute assignment, as trying to do something like this

from typing import NamedTuple 

class Test(NamedTuple): 
    field : bool

test = Test(field=False) 

if test.field := True: 
    print(test.field)

Will result in the following error:

SyntaxError: cannot use named assignment with attribute 

Is it really only possible to update attribute in assignment statements (as opposed to assignment expressions) and if yes why this limitation?

Maldus
  • 5,454
  • 4
  • 17
  • 31

1 Answers1

12

From the pep:

Differences between assignment expressions and assignment statements

Most importantly, since := is an expression, it can be used in contexts where statements are illegal, including lambda functions and comprehensions.

Conversely, assignment expressions don't support the advanced features found in assignment statements:

  • Single assignment targets other than a single NAME are not supported:
    # No equivalent
    a[i] = x
    self.rest = []
    

Seems like it was just made to avoid things that are too complicated (Which is a sign that it should probably be turned into a full statement somewhere). Also, this can already be achieved with setattr:

# This is not that readable, but has the same semantics as what you asked for
if (setattr(test, 'field', new_test_field := ...), new_test_field)[1]:
    ...

# More readable with a helper function
def set_member(obj, member_name, new_value):
    setattr(obj, member_name, new_value)
    return new_value

if set_member(test, 'field', ...):
    ...


# But you might have wanted to check the new `test.field`
# instead of what you assigned it (In case it was a getter/setter descriptor)
def set_member(obj, member_name, new_value):
    setattr(obj, member_name, new_value)
    return getattr(obj, member_name)
Artyer
  • 15,829
  • 2
  • 29
  • 51
  • 2
    Apologies for not reading the pep thoroughly enough. The limitations of the assignment expression are unfortunate, but I guess `setattr` is a close second. Thank you! – Maldus Nov 27 '19 at 07:20
  • This was actually my first attempt to work with assignment expression and the workaround is to use set_member() :) Thanks for the answer – confiq Mar 27 '21 at 15:20