Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot set field value in assignment expression

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?

like image 774
Maldus Avatar asked Nov 24 '19 16:11

Maldus


People also ask

How do I assign a value to an expression in a statement?

A statement attempts to assign a value to an expression. You can assign a value only to a writable variable, property, or array element at run time. The following example illustrates how this error can occur.

How do I assign an expression to a variable in Python?

Expression assignExpr = Expression.Assign ( variableExpr, Expression.Constant ("Hello World!") ); // The block expression allows for executing several expressions sequentually. // In this block, we pass the variable expression as a parameter, // and then assign this parameter a value in the assign expression.

How do you assign a value to a variable in JavaScript?

If the statement assigns a value to an expression, replace the expression with a single writable variable, property, or array element. If the statement makes indirect access through a value type (usually a structure), create a variable to hold the value type. Assign the appropriate structure (or other value type) to the variable.

How do I assign a value only to a writable variable?

You can assign a value only to a writable variable, property, or array element at run time. The following example illustrates how this error can occur. VB. Dim yesterday As Integer ReadOnly maximum As Integer = 45 yesterday + 1 = DatePart (DateInterval.Day, Now) ' The preceding line is an ERROR because of an expression on the left.


1 Answers

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)
like image 195
Artyer Avatar answered Sep 30 '22 05:09

Artyer