
ast.Assign.targets 是一个列表,用于支持链式赋值(如 a = b = c)和解包赋值(如 x, y = 1, 2),其中多个目标变量共享同一右侧表达式;列表结构统一抽象了所有合法左值场景,使 AST 更具通用性与可扩展性。
`ast.assign.targets` 是一个列表,用于支持链式赋值(如 `a = b = c`)和解包赋值(如 `x, y = 1, 2`),其中多个目标变量共享同一右侧表达式;列表结构统一抽象了所有合法左值场景,使 ast 更具通用性与可扩展性。
在 Python 的抽象语法树(AST)中,ast.Assign 节点代表一条赋值语句,其 targets 属性被设计为 list[ast.expr] 类型——不是因为“通常有多个目标”,而是为了统一建模所有合法的赋值左端形式。这种设计兼顾了语义清晰性与实现简洁性。
链式赋值:多个独立目标
最典型的多目标场景是链式赋值:
a = b = c = 42
对应 AST 中 targets 是一个包含三个 Name 节点的列表:
Assign(
targets=[
Name(id='a', ctx=Store()),
Name(id='b', ctx=Store()),
Name(id='c', ctx=Store())
],
value=Constant(value=42)
)
注意:此处每个 Name 都是独立的左值(ctx=Store()),它们并列接收同一个 value 的值,语义等价于 c = 42; b = c; a = b(按从右到左求值)。
解包赋值:单个复合目标
而像 x, y = 1, 2 这样的解包赋值,targets 列表长度仍为 1,但其唯一元素是一个 Tuple(或 List、Set 等可迭代解包目标):
Assign(
targets=[
Tuple(
elts=[Name(id='x', ctx=Store()), Name(id='y', ctx=Store())],
ctx=Store()
)
],
value=Tuple(elts=[Constant(value=1), Constant(value=2)], ctx=Load())
)
此时 targets 是单元素列表,强调“整个元组作为一个整体左值”,而非两个独立目标。
为什么不用多态字段?——设计哲学
若为每种赋值形式定义不同字段(如 single_target, chained_targets, unpack_target),会增加 AST 遍历和工具开发的复杂度。统一用 list[expr] 可以:
- 用统一循环处理所有赋值目标(例如静态分析器检查未声明变量);
- 兼容未来语法扩展(如 PEP 634 中模式匹配的赋值目标);
- 与
ast.AnnAssign、ast.AugAssign等保持接口一致性(后者target为单expr,因其不支持链式)。
注意事项
-
targets列表永远非空(空赋值如= x是语法错误,不会生成有效 AST); - 每个元素必须是带
Store上下文的表达式(如Name,Tuple,Subscript,Attribute),不可是Load或Del; - 链式赋值中
targets[:-1]对应所有被赋值的变量,targets[-1]不存在——最后一个目标由value提供,targets本身只含待写入的位置。
总之,targets 是列表,本质是 AST 对 Python 赋值语法灵活性的精准抽象:既容纳 a = b = c 的并行绑定,也兼容 (x, y) = z 的结构化解包,是编译器前端优雅设计的体现。










