Command Palette

Search for a command to run...

Hectal
Back to the lesson: Topic 10.7 — Types at Run Time: Annotations, get_type_hints and Validation
Python · Example 3 of 3

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.

01

Print the resolved type hints (use get_type_hints) of a function def f(a: int, b: list[str] = []) -> bool.

02

Write field_names(cls) that returns the list of annotated field names of a class, and call it for a small class.

03

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

01

Where does Python store type hints, and how should you read them?

02

What is the difference between how a dataclass and Pydantic use the same hints?

03

What is a forward reference and what changed in Python 3.14?

04

How do type hints help with LLM tool calling?

05

Why can reading __annotations__ fail or mislead, and what do you use instead? What changes on 3.14?

Hints as strings and forward references
Sign in to run this example in your browser.

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