Let's say I have the following class:
from dataclasses import dataclass
from typing import Annotated
@dataclass
class Pizza:
price: Annotated[float, "money"]
size: Annotated[float, "dimension"]
@dataclass
class Topping:
sauce: Annotated[str, "matter"]
These are obviously data classes (i.e. for storing data in other words) but I would like to use them for the type hinting as well. For example, it would be quite straightforward to write a functions like:
def bake_pizza(pizza: Pizza) -> Pizza:
some_operation
return new_pizza
def check_if_vegetarian(topping: Pizza.Topping) -> bool:
some_operation
return True
And the type comparison via e.g. isinstance will work without a problem.
Now my problem is that if I'm using the attributes, I can obviously not do the same, so for example I cannot write a function like:
def calculate_cost(cost: Pizza.price) -> float:
some_calculation
return cost
because price is an attribute and not a class. I know that instead I could write:
def calculate_cost(cost: Pizza.__annotations__["price"]) -> float:
some_calculation
return cost
Then I would get what I want, but it's for us a bit of a problem that depending on whether it's an attribute or a class the notation is so different. So far the only one possibility to do it without having to distinguish between attributes and classes was to use strings, e.g. "Pizza.Topping" or "Pizza.price", but I'm not sure how clean this method is. Does anyone happen to have a better idea?
Toppingjust for type hints? Or is it supposed to be a container for all the toppings on the pizza? Because nested classes are not nested containers (it's not like nested structs in C).Toppingis also a data container in the conventional sense and not made for type hintingdataclasses.fields. If you want this for static typing, your only(?) option is to be proactive: define a type alias, and use that for both the dataclass definition and the function type hint. (I assume your goal is to have just one place to define the "real" type used in both places.)