Class
See Class basics in the docs.
You could use a class with type annotations in the constructor.
class Person:
def __init__(self, name: str, age: int, height: Optional[float]) -> None:
self.name = name
self.age = age
self.height = height
person = Person("Michael", 31, 1.83)
person.name = "Bob"
person.weight = 70
# Error: 'Person' has no attribute 'weight'
But don’t go for a class just for the sake of it.
If all you need is a container of data, no inheritance, and you could write your methods as standalone functions, then go for a typed dictionary instead of a typed class.
That is the Functional Programming way - to pass around data between functions. And now, thanks to type safety, you can validate only allowed object structures are passed to a function - no unexpected types or missing keys anymore. Actually, FP languages like Haskell enforce the type statically and don’t even have classes.
In Python previously, without types, validating a dictionary yourself would be cumbersome. With conditional and additional unit tests. And so you might have resorted to methods on a class which expect values to be set on an instance because of the class’s init method. Even though it wasn’t a good fit.