Uncover the why behind PEP 729. This talk demystifies Python's type system, bridging theory and practice, and explores the challenges across type checkers.
a new way to govern the Python type system: a council that is responsible for maintaining and developing the Python type system." "This PEP was endorsed by maintainers of all major type checkers, including Rebecca Chen (pytype), Eric Traut (Pyright), and privately by maintainers of mypy and Pyre." 3
647, PEP 681, and PEP 695) Jelle Zijlstra (core developer; typeshed; pyanalyze; author of PEP 688 and PEP 702) Shantanu Jain (core developer; typeshed; mypy) 4 Guido van Rossum (core developer; author of PEP 484 and PEP 526) Rebecca Chen (*pytype) *As of today, pytype is maintained by others.
to evolve the specification 3. The type system is underspecified 4. The Steering Council is not well-placed to solve the above problems 5 "... a user of typing has to also think about an external tool, the type checker." "... individual type checkers to decide how to navigate underspecified areas." "… that is often too heavy a process for a small change."
Logic and Proof Theory, and Homotopy Type Theory (HoTT), … HoTT bridges them. 11 Type theory is "a presentation of a specific type system" Ref: Was soll HoTT? by Jacob Neumann
the following ways (Per Martin-Löf's theory): 1. x is an element of the set A <- Programming language uses this typically! ◦ A Python programmer may already know: ▪ True is a boolean type, so True ∈ bool ▪ False is a boolean type, so False ∈ bool 2. x is a proof object for the proposition A 3. x is a program satisfying the specification A 4. x is a solution satisfying the problem A <- This is my favorite one! 13 Expression x ∈ A ∈ = is an element of
🏃 (-5kg) ∈ Lose weight 🥗 (-5kg) ∈ Lose weight 1. 🏃🥗 are solutions to the problem. 2. 🏃 and 🥗 solves the same problem (lose 5kg). solves a different problem (lose 3kg). = ≠ 4. x is an solution in the problem A.
≈🏃≠🥗 ∈ Improve fitness ≠🏃=🥗 ∈ Lost weight ≠ Lost weight = Improve fitness? When you can find… 1. Two solutions to solve both problems. 2. Another equivalent solution for solutions in 1 to solve the same problem. But you can't (as each solution's effect is different).
rule - Problem definition (Set). ◦ A is a set. 2. Introduction rule - Possible solutions (Element). ◦ a is in the set A. 3. Elimination rule - If we pick a solution, how it solves the problem. ◦ What is A, and under what condition a, b, c, … is in A? 4. Equality rule - If we pick a specific solution, it solves the problem. ◦ If we define a and A, then a is in A. 26 A. General rules! (Per Martin-Löf's theory)
header defines the type information (ob_type), the interpreter uses it to determine the valid operations in runtime. 2. type(), isinstance(), issubclass() can be used to check the type in runtime. >>> assert isinstance(∀, object) >>> assert issubclass(bool, object) # bool ∈ PyObject* >>> assert not issubclass(object, bool) >>> assert isinstance(True, bool) # True ∈ bool >>> assert isinstance(False, bool) # False ∈ bool 31
Guido) • Context ◦ Python didn't support a boolean type, while most languages did. ◦ People wrote code like this: True = 1; False = 0; • CPython: Include/boolobject.h / Objects/boolobject.c 32
1. Gradual Typing for Functional Languages by Jeremy Siek (2006) 2. What is gradual typing by Jeremy Siek (2014, March) 3. PEP 483 – The Theory of Type Hints (2014, Dec) 37 Gradual typing theory is "a pay-as-you-go type system"
1. PEP 483 – The Theory of Type Hints 2. Gradual Typing for Functional Languages by Jeremy Siek (2006) 3. What is gradual typing by Jeremy Siek (2014, March) 38 Gradual typing theory is "a pay-as-you-go type system"
RuntimeError? Runtime type consistency Execution Result PS: You may not notice the code is considered "type consistent" by CPython. Type system Input Output
parameters are default assigned the type Any ("?"). ("Any" type is consistent to all types.) b: int = 1 a: any = 1 Whether the types of variables are the same.
functions are the same. def f(x: any) -> any: … def g(x: int) -> int: … Gradual typing theory - rule 1 1. All program parameters are default assigned the type Any ("?"). ("Any" type is consistent to all types.)
g(x: int) -> int: … Gradual typing theory - rule 1 1. All program parameters are default assigned the type Any ("?"). ("Any" type is consistent to all types.)
so any + int = any. a: any = 1 b: int = 1 c = a + b Gradual typing theory - rule 1 1. All program parameters are default assigned the type Any ("?"). ("Any" type is consistent to all types.) 🚨 Note: the major type checker you used today may "infer" the type.
Reject programs that have inconsistencies in the known parts of types (at static time). a: int = 1 def f(x: str): … f(a) OK NG (Incorrect arg-type) Gradual typing theory - rule 2
s: str = 'asdf' f(s) 3. Unknown types with errors can still be caught (at runtime). Ref: mypy:no-errors-reported-for-obviously-wrong-code Python: TypeError: can only concatenate str (not "list") to str Some type checkers (e.g., mypy): No issues Gradual typing theory - rule 3
a new way to govern the Python type system: a council that is responsible for maintaining and developing the Python type system." "This PEP was endorsed by maintainers of all major type checkers, including Rebecca Chen (pytype), Eric Traut (Pyright), and privately by maintainers of mypy and Pyre." 55
*Fast new features adoption. (As of today, pyright provides the best support - ref) pytype Google 2015 Mar Why not mypy? ref 1. Coverage: for untyped codes. 2. Type inference. PyCon 2019 lightning talk by rebecca pyre-check Meta 2017 Nov Why not mypy? ref 1, 2 1. Large-scale code (Instagram) gradual typing adoption. 2. Based on existing solutions in HACK (PHP in meta). pyright Microsoft 2019 Mar Why not mypy? ref 1. IDE integration, language protocol. 2. Speed: A “lazy” or “just-in-time” type evaluator. 3. Not written in python. Static type checkers comparison 👑
*_type(...) may return different results in different type checkers and CPython. 58 reveal_type() / assert_type() in type systems # Before Python 3.11 if typing.TYPE_CHECK: reveal_type(...)
Type Systems TL;DR: A research by RPI and IBM to compare mypy and pytype in 2020. 59 Assignment variable x = e class variable x.attr = e list x[e1] = e2
(untyped) class variable x.attr = e list x[e1] = e2 a = 1 reveal_type(a) a = 's' reveal_type(a) a = [1] reveal_type(a) a.append('s') reveal_type(a) class A: attr = 1 a = A() reveal_type(a.attr) a.attr = 's' reveal_type(a.attr) gh-113255
Zen of Python , which famously states that “There should be one– and preferably only one –obvious way to do it.”" – Python 3 Types in the Wild: A Tale of Two Type Systems "Can we rule the way to develop type checkers?" Takeaways: Problems even though the type systems are based on Type theory and Gradual typing
data a variable can hold. • They are checked at runtime. • e.g., ◦ PEP 285 – Adding a bool type • Type specifications provide optional hints about the expected types of variables, function parameters, and function return values. • They are not always checked at runtime but used by type checkers for static analysis. • e.g., ◦ PEP 484 - Type Hints ◦ PEP 544 - Protocols: Structural subtyping ◦ PEP 673 - Self Type New Specifications
5 changed files with 116 additions and 2 deletions.) # 1. You can use "from typing import Self". __all__ = [ …, 'Self', …] # 2. You can check the Self type and return it. def _type_check(arg, …): if arg in (..., Self, …): return arg … # 3. Explains how to use Self type. @_SpecialForm def Self(self, parameters): … raise TypeError(f"{self} is not subscriptable") 68 That's it!
deletions.) ~8x efforts than CPython • mypy/semanal.py ◦ Semantic analyzer (bind names to definitions + do simple consistency checks). ◦ 📝 Support self type in semantic analysis (in mypy/typeanal.py). • mypy/checker.py ◦ Type checker (do various checks). ◦ 📝 Support expand_self_type (in mypy/expandtype.py). • mypy/nodes.py ◦ Nodes of the abstract syntax tree (AST). ◦ 📝 Support new self type node. 69 PEP 673 - Self Type impl in mypy
Created for CPython. 2. 2021-Dec: Bugged for mypy. 3. 2022-Feb: Bugged and Implemented in CPython. 4. 2022-Nov: Implemented in mypy. 5. 2022-Sep: Bugged for pytype. 6. 2023-Nov: Implemented in pytype. 71 10M Fun fact: Self type annotation is implemented in 3 months, while it can be checked after… 10+ months for mypy, 21+ months for pytype. 3M 21M
Zen of Python , which famously states that “There should be one– and preferably only one –obvious way to do it.”" – Python 3 Types in the Wild: A Tale of Two Type Systems "Can we rule the way to develop type checkers?" "Can we shorten this noticeable time gap to support a new specification to different type checkers?" Takeaways: Problems even though the type systems are based on Type theory and Gradual typing
inputs? OK NG Generics T = TypeVar("whatever") def f(a: T) -> T: return a x: int = 1 y: int = f(x) T = TypeVar("whatever") def f(a: T) -> T: return a x: int = 2 y: str = f(x)