Assignments (reference)¶
This page specifies binding and assignment statements.
Forms¶
| Statement | Targets | Effect |
|---|---|---|
let name = value |
A name | Declares an immutable binding in the current scope. |
mut name = value |
A name | Declares a mutable binding in the current scope. |
name = value |
A name | Reassigns the binding of name in this or an enclosing scope, or else the module's static named name; declares an immutable binding when there is neither. |
name: T = value |
A name | As name = value; value has type T. let and mut accept the annotation too. |
target.field = value |
A field | Writes value to the field of the model or class value target. |
target[index] = value |
An element | Writes value to the element of a list at an int index, to the entry of a dict at a key, or through the __setitem__ method of target's type. |
name op= value, target.field op= value, target[index] op= value |
A name, a field, an element | Writes target op value to the target (see Compound assignment). |
a, b = value |
Names, fields, elements | Assigns the elements of the tuple value to the targets in order. The tuple may be written without parentheses: a, b = b, a. |
let a, b = value, mut a, b = value |
Names | Declares each name, immutable or mutable. |
a = b = value |
Names | Assigns value to each target, from left to right. |
let a = b = value, mut a = b = value |
Names | Declares each name, immutable or mutable, holding value. |
Rules¶
- A
letormutdeclaration in an inner scope shadows an outer binding of the same name until the end of that scope. - A reassigned local binding is
mut. Astaticof the module is reassigned withoutmut(see Static storage). - In
a, b = valueanda = b = value, each name target followsname = value: an existing binding is reassigned, and any other name is declared. - In
a, b = value, when the first target is a name, every target is a name. - The right side of an assignment is evaluated once, before any target is written; a chained assignment of a literal value to targets of different types, below, is the exception.
- In a chained assignment, each target receives the value in its own type. When the targets have different types, a value built only from literals and empty constructors (
None,[],{},list(), a number) is evaluated once for each target, in that target's type. - A field or element write through
selfinside a method, compound forms included, requires amut selfreceiver (INCAN-T0102). - A field write, a
listelement ordictentry write, and a call of a method that changes its receiver (a method declaredmut self, or alist,dictorsetmethod that changes the collection), through any other name, compound and tuple forms included, requires that name to be declaredmut: a binding declared withmut, or a parameter markedmut. A local bound directly to a modulestaticwrites through to the static (see Static storage). - A
forloop, list or dict comprehension or pattern binding changes the item it binds in the place the item belongs to. Aforloop reads its items in place when its body changes one through its variable and it iterates a place: a binding, a field or element of one,enumerateorzipover one, orvalues()of a dict. A list or dict comprehension reads its items in place when its element, key, value or filter changes an item a name of itsforclause binds and it iterates such a place (see Changes through bound names for pattern bindings). A comprehension over any other iterable, such as a call's result or a literal, changes items of its own. - A generator expression holds copies of the items of a place it iterates.
- A closure does not change an outer local it reads (see Closure captures).
d[key]in a write or a changing method call names the valuedstores atkey, and changes it in place; a missing key raisesKeyError.
Refusals¶
| Statement | Refused when | Code |
|---|---|---|
| Any | A reassigned local binding is not mut |
INCAN-T0001 |
| Any | A reassigned name is a marked mut parameter (see mut parameters) |
INCAN-T0001 |
| Any | A reassigned name is a const, or a static imported from another module |
INCAN-T0001 |
| Any | The value's type does not fit a target | INCAN-T0001 |
| Any | A target is an element of a tuple or a str |
INCAN-T0001 |
| Any | A declared name is print or println |
INCAN-T0001 |
target.field = value |
target's type declares no field field, or target is a tuple |
INCAN-T0001 |
target.field = value, target[index] = value |
The name the write goes through (p in p.x and in p.rows[0]) is a local declared without mut, by let or a first plain assignment, or a parameter not marked mut; an element write only when it writes a list element or a dict entry |
INCAN-T0001 |
target.method(...) |
The method changes its receiver, and the name the call goes through (p in p.rows.append(x)) is a local declared without mut or a parameter not marked mut |
INCAN-T0001 |
for item in iterable:, [... for item in iterable], {...: ... for item in iterable} |
The body, element, key, value or filter changes item, by a write, a changing method call or advancing a Generator item, and the loop reads its items in place from a binding declared without mut, a parameter not marked mut, a static or a local bound to one, or self in a plain self method |
INCAN-T0001 |
(... for item in iterable) |
The element or a later clause changes item, and the generator iterates the items of a place: a binding, a field or element of one, enumerate or zip over one, or values() of a dict |
INCAN-T0001 |
target.method(...), target.field = value, target[index] = value |
Inside a closure, the name the change goes through is a local the closure reads from an enclosing function | INCAN-T0001 |
target[index] = value |
target is a str or a tuple, the index is not an int for a list or not a key for a dict, or target's type has no __setitem__ |
INCAN-T0001 |
a, b = value |
value is not a tuple, or the tuple's length differs from the number of targets |
INCAN-T0001 |
a, b = value |
A target is not a name, a field or an element | INCAN-T0001 |
a, b = value |
The first target is a name and a later target is not | INCAN-P0001 |
a = b = value |
The targets have different types, and the value has no fully known type and is not built only from literals and empty constructors (None, [], {}, list(), a number) |
INCAN-T0001 |
a = b = value |
A target is not a name | INCAN-P0001 |
x: T = y = value |
Always | INCAN-P0001 |
model Point:
x: int
y: int
def examples(items: list[int], maybe: Option[int]) -> int:
mut a = 0
mut b = 1
a, b = (b, a + b) # accepted
a, b = b, a # accepted
mut result = items
result[0], result[1] = (result[1], result[0]) # accepted
result[0] = 5 # accepted
result[1] += 1 # accepted
mut point = Point(x=1, y=2)
point.x = 3 # accepted
let origin = Point(x=0, y=0)
origin.x = 1 # refused: origin is not mut
fixed_items = [1]
fixed_items.append(2) # refused: fixed_items is not mut
rows = [[1]]
for row in rows:
row.append(2) # refused: rows is not mut
mut limit: Option[int] = maybe
a = limit = 5 # accepted
let fixed = 10
fixed = 11 # refused: fixed is not mut
x, y = (1, 2, 3) # refused: 3 elements for 2 targets
a, result[0] = (1, 2) # refused: a later target is not a name (INCAN-P0001)
point.z = 1 # refused: Point declares no field z
c: int = d = 1 # refused: annotated chain (INCAN-P0001)
return a