Hints as strings and forward references
With the future import, hints are stored as strings. get_type_hints turns them back into types (here we pass globals() so the class Node can be found) and raises NameError for a name that does not exist.
Hints are ordinary data that Python keeps, so a program can read them: __annotations__, typing.get_type_hints, get_origin and get_args. Dataclasses and Pydantic do exactly this, and so you can write a tiny validator yourself.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 5 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Print the resolved type hints (use get_type_hints) of a function def f(a: int, b: list[str] = []) -> bool.
Write field_names(cls) that returns the list of annotated field names of a class, and call it for a small class.
Create a Pydantic model User with name: str and age: int, build one from age="42", and print user.age + 1.
Explain it without notes
Where does Python store type hints, and how should you read them?
What is the difference between how a dataclass and Pydantic use the same hints?
What is a forward reference and what changed in Python 3.14?
How do type hints help with LLM tool calling?
Why can reading __annotations__ fail or mislead, and what do you use instead? What changes on 3.14?
Expected output
raw: {'value': 'int', 'next': 'Node | None'}
resolved: {'value': <class 'int'>, 'next': __main__.Node | None}
build raw: {'count': 'Missing', 'return': 'int'}
NameError: name 'Missing' is not defined