Types
py4 is statically typed. Every value has a concrete type known at compile time. There is no Any.
Scalar types
| Type | Description |
|---|---|
int | Integer |
float | Floating-point (double) |
bool | Boolean (True / False) |
char | Single character |
str | Immutable string |
None | Unit type, used for functions with no return value |
Composite types
Lists
def main() -> None: xs: list[int] = [1, 2, 3] xs.append(4) print(xs[0]) print(len(xs))Supported element types: int, float, bool, char, str, and class types.
Lists are reference types with refcounted storage. Each element type gets its own specialized runtime.
List operations:
| Operation | Description |
|---|---|
xs.append(v) | Append element |
xs.pop() | Remove and return last element |
xs.clear() | Remove all elements |
xs.copy() | Return a copy |
len(xs) | Length |
xs[i] | Index |
xs[i] = v | Indexed assignment |
for x in xs: | Iteration |
Dictionaries
def main() -> None: counts: dict[str, int] = {"todo": 2, "done": 5} counts["wip"] = 1 print(counts["done"]) print(counts.contains("todo")) print(counts.keys())Supported key types: int, bool, char, str, enum values.
Supported value types: int, float, bool, char, str, enum values, lists, dicts, classes, tuples, and native opaque types.
Dict operations:
| Operation | Description |
|---|---|
d[key] | Get by key (fails if missing) |
d[key] = v | Set by key |
d.get(key) | Get by key (fails if missing) |
d.get_or(key, fallback) | Get with fallback |
d.set(key, value) | Set by key |
d.contains(key) | Membership test → bool |
"key" in d | Membership test → bool |
d.keys() | Returns list[key] |
d.values() | Returns list[value] |
d.items() | Returns list[(key, value)] |
d.pop(key) | Remove and return value |
d.clear() | Remove all entries |
d.copy() | Return a copy |
len(d) | Number of entries |
for k in d: | Key iteration |
for (k, v) in d.items(): | Key-value iteration |
Tuples
def main() -> None: pair: (int, str) = (42, "hello") (n, s) = pair print(n) print(pair[0])Tuples are value types. Indexing is restricted to non-negative integer literals. Tuple shapes get dedicated C structs.
Classes
class Point: x: float y: floatSee Classes for the full reference.
Enums
enum Color: RED GREEN BLUESee Enums for the full reference.
Optional types
Any concrete non-union type can be made nullable with | None:
class Contact: name: str email: str | None score: float | None
def main() -> None: a = Contact("ann", None, 3.5) b = Contact("bob", "bob@example.com", None) print(a) print(b)Optional values can be stored in class fields, tuples, lists, and dictionaries. They cannot be printed directly.
Union types
Selected value types can form a union:
def choose(flag: bool, left: int, right: float) -> int | float: if flag: return left return right
def main() -> None: x: int | float = choose(True, 7, 2.5) print(x)Unions are pragmatic and intentionally narrow. Dict and list types cannot participate in unions.
Native opaque types
io.File and json.Value are managed opaque handles provided by the native stdlib. They cannot be stored in unions.
No generics
There is no generic list[T] or dict[K, V] at runtime. Each combination gets its own specialized C runtime, generated as needed.