[{"data":1,"prerenderedAt":62},["ShallowReactive",2],{"qa-\u002Fpython\u002Ftyping\u002Ftype-hints":3},{"page":4,"siblings":54,"blog":59},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"related":45,"seo":46,"seoDescription":47,"stem":48,"subtopic":49,"topic":50,"topicSlug":51,"updated":52,"__hash__":53},"qa\u002Fpython\u002Ftyping\u002Ftype-hints.md","Type Hints",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","Python","python",{},true,1,"\u002Fpython\u002Ftyping\u002Ftype-hints",[23,28,32,36,41],{"id":24,"difficulty":25,"q":26,"a":27},"hints-runtime-enforced","easy","Are type hints enforced at runtime?","**No.** Type hints are **annotations**, not constraints — the interpreter\nstores them (in `__annotations__`) but **never checks them**. You can pass\na `str` where an `int` is annotated and Python runs it happily; enforcement\nis the job of an **external static type checker** like **mypy** or **pyright**.\n\n```python\ndef double(n: int) -> int:\n    return n * 2\n\ndouble(\"ab\")          # runs fine -> \"abab\", no TypeError\ndouble.__annotations__  # {'n': \u003Cclass 'int'>, 'return': \u003Cclass 'int'>}\n```\n\nIf you want runtime validation you opt in explicitly — e.g. **pydantic**,\n`typing.get_type_hints`, or manual `isinstance` checks. Rule of thumb: hints\ndocument and enable tooling; they are **not** a runtime guard.\n",{"id":29,"difficulty":14,"q":30,"a":31},"optional-union","What is the difference between Optional, Union, and the `|` operator?","`Union[A, B]` means \"**A or B**\". `Optional[X]` is just shorthand for\n`Union[X, None]` — a value that may be `X` **or** `None`. It does **not**\nmean \"optional argument\"; it means \"could be None\". Since Python 3.10 you\ncan write unions with the **`|` operator** instead of importing from `typing`.\n\n```python\nfrom typing import Optional, Union\n\ndef find(id: int) -> Optional[str]: ...     # str or None\ndef parse(x: Union[int, str]) -> int: ...   # int or str\n\n# Python 3.10+ equivalent, no imports:\ndef find(id: int) -> str | None: ...\ndef parse(x: int | str) -> int: ...\n```\n\nPrefer the modern `X | None` syntax on 3.10+. Reach for `Optional`\u002F`Union`\nfrom `typing` only when supporting older versions. Rule of thumb: `Optional`\nis about **nullability**, never about whether a parameter has a default.\n",{"id":33,"difficulty":14,"q":34,"a":35},"list-vs-generics","What is the difference between `list` and `List`, and how do generics work?","Both annotate a list, but **`List` comes from `typing`** while **`list`** is\nthe built-in. Since **Python 3.9** the built-in containers are themselves\n**subscriptable** (`list[int]`, `dict[str, int]`), so `typing.List`,\n`typing.Dict`, etc. are **deprecated** — use the lowercase built-ins. A bare\n`list` means \"list of anything\"; the **generic** form pins the element type.\n\n```python\nfrom typing import List          # legacy\nnames: List[str] = []\n\nnames: list[str] = []            # modern (3.9+), preferred\nscores: dict[str, int] = {}\npair: tuple[int, str] = (1, \"a\")\n```\n\nGenerics let a checker verify element access and method calls. Rule of thumb:\non 3.9+ always parameterize the **built-in** (`list[str]`), and only import\nfrom `typing` for things with no built-in equivalent (e.g. `Callable`).\n",{"id":37,"difficulty":38,"q":39,"a":40},"any-vs-object","hard","What is the difference between `typing.Any` and `object`?","Both accept any value, but they are **opposites to a type checker**. `object`\nis the real **base of every class** — you can assign anything to it, but you\ncan only do `object`-level operations on it. `Any` is an **escape hatch**: it\nis compatible with **everything in both directions**, so the checker stops\nchecking — any attribute or call is allowed.\n\n```python\ndef f(x: object) -> None:\n    x.upper()        # type error: object has no 'upper'\n\ndef g(x: Any) -> None:\n    x.upper()        # OK — Any disables checking\n    x + 1            # also OK, no complaints\n```\n\nUse `object` when you genuinely accept anything but want to **keep type\nsafety** (forcing you to narrow with `isinstance` first). Use `Any` only to\ndeliberately **opt out** of checking. Rule of thumb: `Any` is contagious and\nhides bugs — prefer `object` or a precise type.\n",{"id":42,"difficulty":14,"q":43,"a":44},"what-mypy-does","What does mypy do, and how is it different from Protocol-based typing?","**mypy** is a **static type checker**: it reads your annotations and flags\ntype mismatches **before you run the code** — no execution, no runtime cost.\nBy default it checks types **nominally** (by inheritance). `typing.Protocol`\nadds **structural typing** (a.k.a. duck typing): a class matches a Protocol\nif it has the right **methods\u002Fattributes**, even without inheriting from it.\n\n```python\nfrom typing import Protocol\n\nclass Closable(Protocol):\n    def close(self) -> None: ...\n\ndef shutdown(r: Closable) -> None:\n    r.close()\n\nclass File:                 # never imports\u002Finherits Closable\n    def close(self) -> None: ...\n\nshutdown(File())            # OK — File structurally matches\n```\n\nSo mypy verifies correctness, and `Protocol` lets it accept **anything with\nthe right shape** rather than a specific base class. Rule of thumb: use\nProtocols to type \"**anything that behaves like X**\" without forcing a\ncommon base class.\n",null,{"description":11},"Python interview questions on type hints, Optional and Union, generics with list vs List, typing.Any vs object, mypy, and Protocol structural typing.","python\u002Ftyping\u002Ftype-hints","Type Hints & Annotations","Type Hints & Typing","typing","2026-06-18","-Huf_PnQ17R6ZD2DTYZJptZVH8wQAKCHGmNxduo3rC4",[55,56],{"subtopic":49,"path":21,"order":20},{"subtopic":57,"path":58,"order":12},"Generics & Protocols","\u002Fpython\u002Ftyping\u002Fgenerics-protocols",{"path":60,"title":61},"\u002Fblog\u002Fpython-type-hints-explained","Python Type Hints Explained — Annotations, Optional, and mypy",1781808676582]