9

Python 3.8引入了赋值表达式,允许在条件和 lambda 中赋值,如下所示:

if x := True:
    print(x)

然而,这似乎并没有扩展到属性分配,因为试图做这样的事情

from typing import NamedTuple 

class Test(NamedTuple): 
    field : bool

test = Test(field=False) 

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

将导致以下错误:

SyntaxError: cannot use named assignment with attribute 

是否真的只能更新赋值语句中的属性(而不是赋值表达式),如果是,为什么会有这个限制?

4

1 回答 1

13

从打气:

赋值表达式和赋值语句的区别

最重要的是,因为:=它是一个表达式,所以它可以在语句非法的上下文中使用,包括 lambda 函数和推导式。

相反,赋值表达式不支持赋值语句中的高级特性:

  • NAME不支持 单个以外的单个分配目标:
    # No equivalent
    a[i] = x
    self.rest = []
    

似乎它只是为了避免过于复杂的事情(这表明它可能应该在某处变成完整的声明)。此外,这已经可以通过以下方式实现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)
于 2019-11-24T16:22:27.393 回答