Variables
Typed declaration
def main() -> None: x: int = 42 name: str = "hello" p: Point = Point(1, 2)Type inference
For simple assignments where the right-hand side has a single concrete type, the annotation is optional:
def main() -> None: x = 42 # inferred as int name = "hello" # inferred as str ratio = 2.5 # inferred as float ok = True # inferred as boolAmbiguous cases still require an explicit annotation:
def main() -> None: xs: list[float] = [] # required — [] alone is ambiguous val: str | None = None # required — None alone is ambiguousReassignment
def main() -> None: x: int = 1 x = 2Tuple destructuring
def main() -> None: pair: (int, str) = (10, "hello") (n, s) = pair print(n) print(s)Nested destructuring is supported:
def main() -> None: nested: ((int, float), int) = ((4, 5.5), 6) ((inner_a, inner_b), inner_c): ((int, float), int) = nested print(inner_a) print(inner_b) print(inner_c)A plain name inside a tuple target can bind a whole tuple subvalue directly:
def main() -> None: nested: ((int, float), int) = ((4, 5.5), 6) (whole, c) = nested # whole is (int, float), c is intTop-level variables
Variables can also be declared at module scope:
seed: int = 7base = 4
def main() -> None: print(seed) print(base)Scope
Variables declared inside a function are local to that function. Top-level variables are module-scoped. There is no block scope inside if/while/for.