Skip to content

Files

Latest commit

01e717b · Aug 7, 2021

History

History

10-dp-1class-func

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Jun 11, 2020
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021
Aug 7, 2021

Sample code for Chapter 10 - "Design patterns with first class functions"

From the book "Fluent Python" by Luciano Ramalho (O'Reilly, 2015) http://shop.oreilly.com/product/0636920032519.do

Notes

No issues on file with zero type hints

Running Mypy on classic_strategy.py from the first edition, with no type hints:

$ mypy classic_strategy.py
Success: no issues found in 1 source file

Type inference at play

When the Order.due method made first assignment to discount as discount = 0, Mypy complained:

mypy classic_strategy.py
classic_strategy.py:68: error: Incompatible types in assignment (expression has type "float", variable has type "int")
Found 1 error in 1 file (checked 1 source file)

To fix it, I made the first assigment as discount = 0. I never explicitly declared a type for discount.

Mypy ignores functions with no annotations

Mypy did not raise any issues with this test case:

def test_bulk_item_promo_with_discount(customer_fidelity_0):
    cart = [LineItem('banana', 30, .5),
            LineItem('apple', 10, 1.5)]
    order = Order(customer_fidelity_0, 10, BulkItemPromo())
    assert order.total() == 30.0
    assert order.due() == 28.5

The second argument to Order is declared as Sequence[LineItem]. Mypy only checks the body of a function the signature as at least one annotation, like this:

def test_bulk_item_promo_with_discount(customer_fidelity_0) -> None:
    cart = [LineItem('banana', 30, .5),
            LineItem('apple', 10, 1.5)]
    order = Order(customer_fidelity_0, 10, BulkItemPromo())
    assert order.total() == 30.0
    assert order.due() == 28.5

Now Mypy complains that "Argument 2 of Order has incompatible type".

However, even with the annotation in the test function signature, Mypy did not find any problem when I mistyped the name of the cart argument. Here, cart_plain should be cart:

def test_bulk_item_promo_with_discount(customer_fidelity_0) -> None:
    cart = [LineItem('banana', 30, .5),
            LineItem('apple', 10, 1.5)]
    order = Order(customer_fidelity_0, cart_plain, BulkItemPromo())
    assert order.total() == 30.0
    assert order.due() == 28.5

Hypotesis: cart_plain is a function decorated with @pytest.fixture, and at the top of the test file I told Mypy to ignore the Pytest import:

import pytest  # type: ignore