I have a python function that utilizes the python __pow__ (**) operator with two int's, Mypy tells me that the expression b ** e
has type "Any", where b and e have type "int". I have tried to cast the expression to an int with int(b ** e)
, but I still get the error. How do I correctly type hint this expression?
Also, if the expression b ** e
really does return type "Any", can you explain why?
Error:
temp.py:7: error: Expression has type "Any" [misc]
power: Callable[[int, int], int] = lambda b, e: b ** e
^
temp.py
from functools import reduce
from typing import Callable, Dict
def factorization_product(fact: Dict[int, int]) -> int:
'''returns the product which has the prime factorization of fact'''
power: Callable[[int, int], int] = lambda b, e: b ** e # error on expression "b ** e"
product: Callable[[int, int], int] = lambda x, y: x * y
return reduce(product, [power(b, e) for b, e in fact.items()], 1)
Edit:
I realized I can use the builtin pow and operator.mul instead of lambda's, but I still get the error.
Error:
temp.py:8: error: Expression has type "Any" [misc]
return reduce(mul, [pow(b, e) for b, e in fact.items()], 1)
^
revised temp.py
from functools import reduce
from operator import mul
from typing import Dict
def factorization_product(fact: Dict[int, int]) -> int:
'''returns the product which has the prime factorization of fact'''
return reduce(mul, [pow(b, e) for b, e in fact.items()], 1)
Checking typeshed shows that an
int
is returned only for the specialized case of squaring a number (x
of typeLiteral[2]
). This is because even thoughb
ande
areint
s,e
may be negative, in which case the result is afloat
. Since the result can be afloat
orint
, it looks liketypeshed
went withAny
for the general case.I'd say this is a language limitation. Ideally we could use
@overload
on all non-negative integes forx
, butLiteral
only supports specific values.To get around this while also using
--disallow-any-expr
, use typing.cast like so:Running
mypy --disallow-any-expr temp.py
now returnsSuccess: no issues found in 1 source file
.But before you blindly add the
cast
, consider the scenario I brought up wheree
is negative, causing type checking to succeed but the runtime to fail if you doint
-specific manipulation with the result offactorization_product
. You may want to add validation here. For example, with no validation:fails at run-time with
can't multiply sequence by non-int of type 'float'
despitemypy
reporting type-check success.