Mypy Examples

Here are some mypy example programs. Each example has dynamically typed Python/mypy code and equivalent statically typed mypy code side by side. Every program is still valid Python 3.x. All differences between the variants are highlighted.

Word frequencies with a dictionary

Mypy with dynamic typing
# Display the frequencies of words in a file.

import sys
import re


if not sys.argv[1:]:
    raise RuntimeError('Usage: wordfreq FILE')

d = {}

with open(sys.argv[1]) as f:
    for s in f:
        for word in re.sub('\W', ' ', s).split():
            d[word] = d.get(word, 0) + 1

# Use list comprehension
l = [(freq, word) for word, freq in d.items()]

for freq, word in sorted(l):
    print('%-6d %s' % (freq, word))
Mypy with static typing
# Display the frequencies of words in a file.

import sys
import re
from typing import Dict

if not sys.argv[1:]:
    raise RuntimeError('Usage: wordfreq FILE')

d = {}  # type: Dict[str, int]

with open(sys.argv[1]) as f:
    for s in f:
        for word in re.sub('\W', ' ', s).split():
            d[word] = d.get(word, 0) + 1

# Use list comprehension
l = [(freq, word) for word, freq in d.items()]

for freq, word in sorted(l):
    print('%-6d %s' % (freq, word))

In this example we add an explicit type declaration for the variable d, as it is not obvious from the local context.

Simple class

Mypy with dynamic typing
class BankAccount:
    def __init__(self, initial_balance=0):
        self.balance = initial_balance
    def deposit(self, amount):
        self.balance += amount
    def withdraw(self, amount):
        self.balance -= amount
    def overdrawn(self):
        return self.balance < 0

my_account = BankAccount(15)
my_account.withdraw(5)
print(my_account.balance)
Mypy with static typing
class BankAccount:
    def __init__(self, initial_balance: int = 0) -> None:
        self.balance = initial_balance
    def deposit(self, amount: int) -> None:
        self.balance += amount
    def withdraw(self, amount: int) -> None:
        self.balance -= amount
    def overdrawn(self) -> bool:
        return self.balance < 0

my_account = BankAccount(15)
my_account.withdraw(5)
print(my_account.balance)

In this example we chose to use integers to represent balance. This would be fine in a game, for example, but in other applications a different type would make more sense.

This example was adapted from the Python wiki (with the standard Python license).

Prime number sieve with generators

Mypy with dynamic typing
import itertools


def iter_primes():
     # An iterator of all numbers between 2 and
     # +infinity
     numbers = itertools.count(2)

     # Generate primes forever
     while True:
         # Get the first number from the iterator
         # (always a prime)
         prime = next(numbers)
         yield prime

         # This code iteratively builds up a chain
         # of filters...
         numbers = filter(prime.__rmod__, numbers)

for p in iter_primes():
    if p > 1000:
        break
    print(p)
Mypy with static typing
import itertools
from typing import Iterator

def iter_primes() -> Iterator[int]:
     # An iterator of all numbers between 2 and
     # +infinity
     numbers = itertools.count(2)

     # Generate primes forever
     while True:
         # Get the first number from the iterator
         # (always a prime)
         prime = next(numbers)
         yield prime

         # This code iteratively builds up a chain
         # of filters...
         numbers = filter(prime.__rmod__, numbers)

for p in iter_primes():
    if p > 1000:
        break
    print(p)

Like the bank account example, this was adapted from the Python wiki.