119
Static Typing in Python EuroPython 2020 @di_codes

Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

  • Upload
    others

  • View
    50

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Static Typing in PythonEuroPython 2020

@di_codes

Page 2: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Hi, I'm Dustin

• Developer Advocate @ Google• PyTexas (Austin, TX, Oct 24-25th 2020)• Python Package Index

@di_codes

Page 3: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Pop quiz:Is Python dynamically or statically typed?

@di_codes

Page 4: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Answer:Dynamically typed... but can optionally be statically typed.

@di_codes

Page 5: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Steps to understand that:

• Types in Python• Type systems in general• Dynamic typing in Python• Static typing in Python

@di_codes

Page 6: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Once we understand that:

• How to use static typing• When you should use static typing• When you shouldn't use static typing

@di_codes

Page 7: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Let's talk about

types (and type)

@di_codes

Page 8: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> type(42)<class 'int'>

@di_codes

Page 9: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> type(42)<class 'int'>>>> type(42.0)<class 'float'>

@di_codes

Page 10: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> type(42)<class 'int'>>>> type(42.0)<class 'float'>>>> type('foo')<class 'str'>

@di_codes

Page 11: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> type(42)<class 'int'>>>> type(42.0)<class 'float'>>>> type('foo')<class 'str'>>>> type(['foo', 'bar'])<class 'list'>

@di_codes

Page 12: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> a = 4242

@di_codes

Page 13: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> a = 4242>>> float(42)42.0

@di_codes

Page 14: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> a = 4242>>> float(42)42.0>>> str(float(42))'42.0'

@di_codes

Page 15: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> a = 4242>>> float(42)42.0>>> str(float(42))'42.0'>>> list(str(float(42)))['4', '2', '.', '0']

@di_codes

Page 16: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> type(42) is intTrue>>> int<class 'int'>>>> isinstance(42, int)True

@di_codes

Page 17: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> type(None)<class 'NoneType'>>>> def func():... pass...>>> type(func)<class 'function'>>>> type(...)<class 'ellipsis'>

@di_codes

Page 18: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> import types

@di_codes

Page 19: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> import types>>> dir(types)['AsyncGeneratorType', 'BuiltinFunctionType','BuiltinMethodType', 'ClassMethodDescriptorType','CodeType', 'CoroutineType', 'DynamicClassAttribute','FrameType', 'FunctionType', 'GeneratorType','GetSetDescriptorType', 'LambdaType','MappingProxyType', 'MemberDescriptorType','MethodDescriptorType', 'MethodType','MethodWrapperType', 'ModuleType', 'SimpleNamespace','TracebackType', 'WrapperDescriptorType',...

@di_codes

Page 20: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Dynamic typingVariables can be any type

@di_codes

Page 21: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> import random>>> a = random.choice([42, 42.0, '42'])>>> type(a)

@di_codes

Page 22: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> import random>>> a = random.choice([42, 42.0, '42'])>>> type(a) # Could be str, int, float

@di_codes

Page 23: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Dynamic typingArguments and return values of functions can be any type

@di_codes

Page 24: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate(a, b, c): "Frobnicates the bizbaz" return a + b + c

@di_codes

Page 25: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> def frobnicate(a, b, c):... return a + b + c

@di_codes

Page 26: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> def frobnicate(a, b, c):... return a + b + c>>> frobnicate(1, 2, 3)6

@di_codes

Page 27: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> def frobnicate(a, b, c):... return a + b + c>>> frobnicate(1, 2, 3)6>>> frobnicate('hi', ' ', 'there')'hi there'

@di_codes

Page 28: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> def frobnicate(a, b, c):... return a + b + c>>> frobnicate(1, 2, 3)6>>> frobnicate('hi', ' ', 'there')'hi there'>>> frobnicate(1, 2, 'foo')Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in frobnicateTypeError: unsupported operand type(s) for +: 'int'and 'str'

@di_codes

Page 29: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate(a, b, c): """Frobnicates the bizbaz

Args: a (int): The first parameter. b (int): The second parameter. c (int): The third parameter.

Returns: int: The bizbaz """ return a + b + c

@di_codes

Page 30: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate(a, b, c): "Frobnicates the bizbaz" assert type(a) is int assert type(b) is int assert type(c) is int bizbaz = a + b + c assert type(bizbaz) is int return bizbaz

@di_codes

Page 31: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Duck typingIf it walks like a duck and it quacks like a duck...

@di_codes

Page 32: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

foo = [f(x) for x in bar]

foo = bar > 0

foo = bar(...)

@di_codes

Page 33: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Static typingAs in, defined and not changing

@di_codes

Page 34: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

int frobnicate(int a, int b, int c) { return a + b + c;}

@di_codes

Page 35: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

public static int frobnicate(int a, int b, int c) { return a + b + c;}

@di_codes

Page 36: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

fn frobnicate(a: u8, b: u8, c: u8) -> u8 { return a + b + c;}

@di_codes

Page 37: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

function frobnicate(a: number, b: number, c:number): number { return a + b + c;}

@di_codes

Page 38: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Dynamic Static• Python • C/C++• Ruby • Rust• Clojure • Java• JavaScript • TypeScript

@di_codes

Page 39: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Dynamic Static• Python* • C/C++• Ruby • Rust• Clojure • Java• JavaScript • TypeScript

* Kinda. @di_codes

Page 40: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Python is dynamically typedBut can optionally be statically typed

@di_codes

Page 41: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 42: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

PEP 3107Function Annotations

@di_codes

Page 43: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate(a, b, c): "Frobnicates the bizbaz" return a + b + c

@di_codes

Page 44: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate(a: 'x', b: 5 + 6, c: []) -> max(2, 9): "Frobnicates the bizbaz" return a + b + c

@di_codes

Page 45: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> def frob(a: 'x', b: 5 + 6, c: []) -> max(2, 9):... return a + b + c...>>> frob.__annotations__{'a': 'x', 'b': 11, 'c': [], 'return': 9}

@di_codes

Page 46: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

• Providing typing information  • Type checking  • Let IDEs show what types a function expects/returns  • Function overloading / generic functions  • Foreign-language bridges  • Adaptation  • Predicate logic functions  • Database query mapping  • RPC parameter marshaling

• Other information  • Documentation for parameters and return values

@di_codes

Page 47: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

>>> def frobnicate(a: int, b: int, c: int) -> int:... return a + b + c...>>> frobnicate.__annotations__{'a': int, 'b': int, 'c': int, 'return': int}

@di_codes

Page 48: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Jukka LehtosaloUniversity of Cambridge

@di_codes

Page 49: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

UnificationOf statically typed and dynamically typed languages

@di_codes

Page 50: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Using the same languageFor tiny scripts and sprawling, multi-million line codebases

@di_codes

Page 51: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Gradual growthfrom an untyped prototype to a statically typed product

@di_codes

Page 52: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 53: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

"Adding a static type system to a dynamically-typed language can be an invasive change that requires coordinated modification of existing programs, virtual machines and development tools."— Jukka Lehtosalo

@di_codes

Page 54: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

"Optional pluggable type systems do not affect runtime semantics of programs, and thus they can be added to a language without affecting existing code and tools."— Jukka Lehtosalo

@di_codes

Page 55: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 56: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

"Mypy is an experimental variant of Python that supports writing programs that seamlessly mix dynamic and static typing."— Jukka Lehtosalo

@di_codes

Page 57: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

int fib(int n): if n <= 1: return n else: return fib(n - 1) + fib(n - 2)

@di_codes

Page 58: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

"I eventually presented my project at the PyCon 2013 conference in Santa Clara, and I chatted about it with Guido van Rossum, the BDFL of Python. He convinced me to drop the custom syntax and stick to straight Python 3 syntax."— Jukka Lehtosalo

@di_codes

Page 59: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

PEP 483The Theory of Type Hints

@di_codes

Page 60: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Optional typingOnly gets in your way if you want it to get in your way

@di_codes

Page 61: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Gradual typingLet's not try to do this all at once

@di_codes

Page 62: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Variable annotationsFor annotating more than just functions

@di_codes

Page 63: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate(a: int, b: int, c: int) -> int: bizbaz = a + b + c return bizbaz

@di_codes

Page 64: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate(a: int, b: int, c: int) -> int: bizbaz = a + b + c # type: int return bizbaz

@di_codes

Page 65: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Type hinting for Python 2Because even those stuck in the past deserve static typing

@di_codes

Page 66: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

# Python 3def frobnicate(a: int, b: int, c: int) -> int: return a + b + c

# Python 2def frobnicate(a, b, c): # type: (int, int, int) -> int return a + b + c

@di_codes

Page 67: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Special type constructsFundamental building blocks we need to do static typing

@di_codes

Page 68: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

• Existing types: int, float, str, NoneType, etc.

• New types: (from typing import ...)   • Any: consistent with any type   • Union[t1, t2, ...]: at least one of t1, t2, etc.   • Optional[t1]: alias for Union[t1, NoneType]   • Tuple[t1, t2, ...]: tuple whose items are t1, etc.   • Callable[[t1, t2, ...], tr]: a function

@di_codes

Page 69: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

def frobnicate( a: int, b: int, c: Union[int, float]) -> Union[int, float]: return a + b + c

@di_codes

Page 70: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Container typesFor defining types inside container classes

@di_codes

Page 71: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

users = [] # type: List[int]users.append(42) # OKusers.append('Some Guy') # fails

examples = {} # type: Dict[str, int]examples['Some Guy'] = 42 # OKexamples[2] = None # fails

@di_codes

Page 72: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Generic typesFor when a class or function behaves in a generic manner

@di_codes

Page 73: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

from typing import Iterable

class Task: ...

def work(todo_list: Iterable[Task]) -> None: ...

@di_codes

Page 74: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Type aliasesTo be more succinct

@di_codes

Page 75: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

from typing import Unionfrom decimal import Decimal

Number = Union[int, float, complex, Decimal]

def frob(a: Number, b: Number, c: Number) -> Number: "Frobnicates the bizbaz" return a + b + c

@di_codes

Page 76: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

PEP 484Type Hints

@di_codes

Page 77: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Python 3.5Released: September 13, 2015

@di_codes

Page 78: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

PEP 526Syntax for Variable Annotations

@di_codes

Page 79: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

# 'primes' is a list of integersprimes = [] # type: List[int]

# 'captain' is a string (initial value is a problem!)captain = ... # type: str

class Starship: # 'stats' is a class variable stats = {} # type: Dict[str, int]

@di_codes

Page 80: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

# 'primes' is a list of integersprimes: List[int] = []

# 'captain' is a string (initial value is a problem!)captain = ... # type: str

class Starship: # 'stats' is a class variable stats = {} # type: Dict[str, int]

@di_codes

Page 81: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

# 'primes' is a list of integersprimes: List[int] = []

# 'captain' is a stringcaptain: str # Note: no initial value!

class Starship: # 'stats' is a class variable stats = {} # type: Dict[str, int]

@di_codes

Page 82: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

# 'primes' is a list of integersprimes: List[int] = []

# 'captain' is a stringcaptain: str # Note: no initial value!

class Starship: # 'stats' is a class variable stats: ClassVar[Dict[str, int]] = {}

@di_codes

Page 83: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Python 3.6Released: December 23, 2016

@di_codes

Page 84: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Type checkersStatic vs. dynamic

@di_codes

Page 85: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 86: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ pip install mypy...

$ cat frob.pydef frobnicate(a: int, b: int, c: int) -> int: return a + b + c

frobnicate('hi', ' ', 'there')

$ mypy frob.pyfrob.py:4: error: Argument 1 to "frobnicate" has incompatible type"str"; expected "int"frob.py:4: error: Argument 2 to "frobnicate" has incompatible type"str"; expected "int"frob.py:4: error: Argument 3 to "frobnicate" has incompatible type"str"; expected "int"

@di_codes

Page 87: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

• Static  • mypy (Dropbox)  • pytype (Google)  • pyre (Facebook)  • pyright (Microsoft)  • PyCharm, $YOUR_EDITOR

• Dynamic  • enforce, typeguard, typo, ducktype, strictconf, etc.

@di_codes

Page 88: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Differences between mypy and pytypeCross-function inference, runtime lenience

@di_codes

Page 89: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

# example.py

def f(): return "EuroPython"

def g(): return f() + 2020

g()

@di_codes

Page 90: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ python example.pyTraceback (most recent call last): File "example.py", line 5, in <module> g() File "example.py", line 4, in g return f() + 2020TypeError: can only concatenate str (not "int") to str

@di_codes

Page 91: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ mypy example.py

                                                                 

@di_codes

Page 92: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ mypy example.py

$

                                                                 

@di_codes

Page 93: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ mypy example.py

$ pytype example.py

                                                                 

@di_codes

Page 94: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ mypy example.py

$ pytype example.pyComputing dependenciesAnalyzing 1 sources with 0 local dependencies[1/1] check testFAILED: /tmp/.pytype/pyi/example.pyi pytype-single --imports_info/tmp/.pytype/imports/test.imports --module-name test -V 3.7 -o/tmp/.pytype/pyi/test.pyi --analyze-annotated --nofail --quick/tmp/example.pyFile "/tmp/example.py", line 4, in g: unsupported operand type(s)for +: 'str' and 'int' [unsupported-operands] Function __add__ on str expects str

For more details, seehttps://google.github.io/pytype/errors.html#unsupported-operands.

@di_codes

Page 95: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

# example.py

from typing import List

def f() -> List[str]: lst = ["PyCon"] lst.append(2020) return [str(x) for x in lst]

print(f())

@di_codes

Page 96: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ python example.py['PyCon', '2020']

@di_codes

Page 97: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ pytype example.pyComputing dependenciesAnalyzing 1 sources with 0 local dependenciesninja: Entering directory `/private/tmp/.pytype'[1/1] check exampleSuccess: no errors found

@di_codes

Page 98: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

$ pytype example.pyComputing dependenciesAnalyzing 1 sources with 0 local dependenciesninja: Entering directory `/private/tmp/.pytype'[1/1] check exampleSuccess: no errors found

$ mypy example.pyexample.py:7: error: Argument 1 to "append" of "list"has incompatible type "int"; expected "str"

@di_codes

Page 99: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

y thoWhen (and why) we should use static typing

@di_codes

Page 100: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

When you shouldn't use static typingBasically never

@di_codes

Page 101: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Static typing:Not a replacement for unit tests

@di_codes

Page 102: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

When you should use static typingBasically as much as possible

@di_codes

Page 103: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Use static typing:

When you're millions-of-lines scale

@di_codes

Page 104: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

"At our scale—millions of lines of Python—the dynamic typing in Python made code needlessly hard to understand and started to seriously impact productivity."— Jukka Lehtosalo

@di_codes

Page 105: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 106: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 107: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 108: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

@di_codes

Page 109: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Use static typing:

When your code is confusing

@di_codes

Page 110: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Use static typing:

When your code is for public consumption

@di_codes

Page 111: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Use static typing:

Before migrating or refactoring

@di_codes

Page 112: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Use static typing:

To experiment with static typing

@di_codes

Page 113: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

How to use static typing in PythonIn just five easy steps!

@di_codes

Page 114: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

1.Migrate to Python >= 3.6 (optional)

@di_codes

Page 115: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

1.Migrate to Python >= 3.6 (optional)2.Install a typechecker locally

@di_codes

Page 116: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

1.Migrate to Python >= 3.6 (optional)2.Install a typechecker locally3.Start optionally typing your codebase

@di_codes

Page 117: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

1.Migrate to Python >= 3.6 (optional)2.Install a typechecker locally3.Start optionally typing your codebase4.Run a typechecker with your linting

@di_codes

Page 118: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

1.Migrate to Python >= 3.6 (optional)2.Install a typechecker locally3.Start optionally typing your codebase4.Run a typechecker with your linting5.Convince all your coworkers to join you

@di_codes

Page 119: Static Typing in Python · Steps to understand that: • Types in Python • Type systems in general • Dynamic typing in Python • Static typing in Python @di_codes

Thanks! @di_codes