How to start using types in Python with Mypy
Carlos Villavicencio Ecuadorian 󰎸 Software Developer at Stack Builders Community leader Amateur photographer cvillavicencio cvillavicencio@stackbuilders.com @po5i po5i Quilotoa Lake, Ecuador 2020. 大家好!
Types and Python
Data Structures Primitive Non-primitive Integer Float String Boolean Array List Tuple Dictionary Set File Linear Non-linear Stacks Queues Graphs Trees
Types are known in compilation time Variables bind to types Very verbose Bytecode is well optimized in memory Types are known in runtime Variables bind to objects 🦆 Less verbose Bugs in run-time are very common Dynamic vs. Static Languages
Weakly vs. Strongly Type System Implicit coercion between non-related types Flexibles Unpredictables Explicit type conversion (casting) Strict rules on the static analysis. Type Safety
Static type checking in Python But you can also use
Type Annotations
meat: str = "Beef" weight_pounds: float = "0.5" # mypy # error: Incompatible types in assignment # (expression has type "str", variable has type "float") Primitive types 🦕
Let’s prepare some 🍔 def make_hamburger(meat, number_of_meats): return ["bread"] + [meat] * number_of_meats + ["bread"] print(make_hamburger("BEEF", 2)) # ['bread', 'BEEF', 'BEEF', 'bread']
class MyTest(unittest.TestCase): def test_make_hamburger_returns_list(self): self.assertTrue(isinstance(make_hamburger("beef", 2), list)) def test_empty_make_hamburger_returns_breads(self): self.assertEqual(make_hamburger(None, 0), ['bread', 'bread']) def test_invalid_make_hamburger_raises(self): with self.assertRaises(TypeError): make_hamburger() Unit testing?
from typing import List def make_hamburger(meat: str, number_of_meats: int) -> List[str]: return ["bread"] + [meat] * number_of_meats + ["bread"] The `typing`module
from typing import List Hamburger = List[str] def make_hamburger(meat: str, number_of_meats: int) -> Hamburger: return ["bread"] + [meat] * number_of_meats + ["bread"] Type Alias
from typing import List, Optional Hamburger = List[str] Extras = Optional[List[str]] def make_hamburger(meat: str, number_of_meats: int, extras: Extras) -> Hamburger: if extras: return ["bread"] + extras + [meat] * number_of_meats + ["bread"] else: return ["bread"] + [meat] * number_of_meats + ["bread"] print(make_hamburger("Beef", 2, ['tomatoes', 'pickles'])) # ['bread', 'tomatoes', 'pickles', 'Beef', 'Beef', 'bread'] Optionals 🍅
from typing import TypeVar, List T = TypeVar("T", int, List[str]) def generic_add(x: T, y: T) -> T: return x + y Generics 󰟲
x1: int = 5 y1: int = 2 print(generic_add(x1, y1)) # 7 x2: List[str] = ["Hello"] y2: List[str] = ["World"] print(generic_add(x2, y2)) # ['Hello', 'World'] x3: str = "foo" y3: str = "bar" print(generic_add(x3, y3)) # mypy error: Value of type variable "T" of "generic_add" cannot be "str" Generics 󰟲
from typing import Union Number = Union[float, int] def union_add(x: Number, y: Number) -> Number: return x + y Union Types
x1: int = 5 y1: float = 2.5 print(union_add(x1, y1)) # 7 x2: int = 2 y2: str = "1" print(union_add(x2, y2)) # error: Argument 1 to "union_add" has incompatible type "str"; expected "Union[float, int]" # error: Argument 2 to "union_add" has incompatible type "str"; expected "Union[float, int]" Union Types
from typing import Callable def sum_and_process(a: int, b: int, callback: Callable[[int], bool]) -> bool: total = a + b return callback(total) def is_positive(val: int) -> bool: return val > 0 output = sum_and_process(5, 2, is_positive) print(output) # True Callables
谢谢! ευχαριστώ Obrigado! ¡Gracias! Thank You! Check out my tutorial

How to start using types in Python with mypy

  • 1.
    How to startusing types in Python with Mypy
  • 2.
    Carlos Villavicencio Ecuadorian 󰎸 Software Developerat Stack Builders Community leader Amateur photographer cvillavicencio cvillavicencio@stackbuilders.com @po5i po5i Quilotoa Lake, Ecuador 2020. 大家好!
  • 3.
  • 4.
    Data Structures Primitive Non-primitive IntegerFloat String Boolean Array List Tuple Dictionary Set File Linear Non-linear Stacks Queues Graphs Trees
  • 7.
    Types are knownin compilation time Variables bind to types Very verbose Bytecode is well optimized in memory Types are known in runtime Variables bind to objects 🦆 Less verbose Bugs in run-time are very common Dynamic vs. Static Languages
  • 8.
    Weakly vs. StronglyType System Implicit coercion between non-related types Flexibles Unpredictables Explicit type conversion (casting) Strict rules on the static analysis. Type Safety
  • 9.
    Static type checking inPython But you can also use
  • 10.
  • 11.
    meat: str ="Beef" weight_pounds: float = "0.5" # mypy # error: Incompatible types in assignment # (expression has type "str", variable has type "float") Primitive types 🦕
  • 12.
    Let’s prepare some🍔 def make_hamburger(meat, number_of_meats): return ["bread"] + [meat] * number_of_meats + ["bread"] print(make_hamburger("BEEF", 2)) # ['bread', 'BEEF', 'BEEF', 'bread']
  • 13.
    class MyTest(unittest.TestCase): def test_make_hamburger_returns_list(self): self.assertTrue(isinstance(make_hamburger("beef",2), list)) def test_empty_make_hamburger_returns_breads(self): self.assertEqual(make_hamburger(None, 0), ['bread', 'bread']) def test_invalid_make_hamburger_raises(self): with self.assertRaises(TypeError): make_hamburger() Unit testing?
  • 14.
    from typing importList def make_hamburger(meat: str, number_of_meats: int) -> List[str]: return ["bread"] + [meat] * number_of_meats + ["bread"] The `typing`module
  • 15.
    from typing importList Hamburger = List[str] def make_hamburger(meat: str, number_of_meats: int) -> Hamburger: return ["bread"] + [meat] * number_of_meats + ["bread"] Type Alias
  • 16.
    from typing importList, Optional Hamburger = List[str] Extras = Optional[List[str]] def make_hamburger(meat: str, number_of_meats: int, extras: Extras) -> Hamburger: if extras: return ["bread"] + extras + [meat] * number_of_meats + ["bread"] else: return ["bread"] + [meat] * number_of_meats + ["bread"] print(make_hamburger("Beef", 2, ['tomatoes', 'pickles'])) # ['bread', 'tomatoes', 'pickles', 'Beef', 'Beef', 'bread'] Optionals 🍅
  • 17.
    from typing importTypeVar, List T = TypeVar("T", int, List[str]) def generic_add(x: T, y: T) -> T: return x + y Generics 󰟲
  • 18.
    x1: int =5 y1: int = 2 print(generic_add(x1, y1)) # 7 x2: List[str] = ["Hello"] y2: List[str] = ["World"] print(generic_add(x2, y2)) # ['Hello', 'World'] x3: str = "foo" y3: str = "bar" print(generic_add(x3, y3)) # mypy error: Value of type variable "T" of "generic_add" cannot be "str" Generics 󰟲
  • 19.
    from typing importUnion Number = Union[float, int] def union_add(x: Number, y: Number) -> Number: return x + y Union Types
  • 20.
    x1: int =5 y1: float = 2.5 print(union_add(x1, y1)) # 7 x2: int = 2 y2: str = "1" print(union_add(x2, y2)) # error: Argument 1 to "union_add" has incompatible type "str"; expected "Union[float, int]" # error: Argument 2 to "union_add" has incompatible type "str"; expected "Union[float, int]" Union Types
  • 21.
    from typing importCallable def sum_and_process(a: int, b: int, callback: Callable[[int], bool]) -> bool: total = a + b return callback(total) def is_positive(val: int) -> bool: return val > 0 output = sum_and_process(5, 2, is_positive) print(output) # True Callables
  • 23.