问题
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?
回答1:
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 decorator)
def set_member(obj, member_name, new_value):
setattr(obj, member_name, new_value)
return getattr(obj, member_name)
来源:https://stackoverflow.com/questions/59019647/cannot-set-field-value-in-assignment-expression