darda
darda

Reputation: 4174

Mypy and `None`

Take the following function:

from typing import Optional


def area_of_square(width: Optional[float] = None, 
                   height: Optional[float] = None) -> float:
    if width is None and height is None:
        raise ValueError('You have not specified a width or height')
    if width is not None and height is not None:
        raise ValueError('Please specify a width or height, not both')

    area = width**2 if width is not None else height**2
    return area

At the area = line, mypy complains that height could be None.

I could add the following line just above it:

    height = typing.cast(int, height)

But that is not correct, since height could be None. Wrapping that cast in any sort of logic makes mypy get lost and I'm back to the error.

I personally use typing for readability and to avoid bugs. Getting errors like this (and often with lazy initialization and other similar uses of None) kind of defeats the purpose, so I like to fix them when it makes sense.

What are some strategies people use in this scenario?

Upvotes: 1

Views: 3991

Answers (1)

STerliakov
STerliakov

Reputation: 7923

mypy cannot bind multiple variables with one common condition.

The following lines type guard both variables:

a is None and b is None
a is not None and b is not None

So they work as expected, while another condition:

a is not None or b is not None

is not informative for mypy, you cannot express "at least one of them is not None" and use it in type checking.

I'd do this instead:

from typing import Optional


def area_of_square(width: Optional[float] = None, 
                   height: Optional[float] = None) -> float:
    if width is not None and height is not None:
        raise ValueError('Please specify a width or height, not both')
    elif width is not None:
        area = width**2 
    elif height is not None:
        area = height**2
    else:
        raise ValueError('You have not specified a width or height')
    return area

Upvotes: 4

Related Questions