Duck type compatibility
In Python, certain types are compatible even though they aren’t subclasses ofeach other. For example, int
objects are valid whenever float
objectsare expected. Mypy supports this idiom via duck type compatibility. This issupported for a small set of built-in types:
int
is duck type compatible withfloat
andcomplex
.float
is duck type compatible withcomplex
.- In Python 2,
str
is duck type compatible withunicode
.
For example, mypy considers an int
object to be valid whenever afloat
object is expected. Thus code like this is nice and cleanand also behaves as expected:
- import math
- def degrees_to_radians(degrees: float) -> float:
- return math.pi * degrees / 180
- n = 90 # Inferred type 'int'
- print(degrees_to_radians(n)) # Okay!
You can also often use Protocols and structural subtyping to achieve a similar effect ina more principled and extensible fashion. Protocols don’t apply tocases like int
being compatible with float
, since float
is nota protocol class but a regular, concrete class, and many standard libraryfunctions expect concrete instances of float
(or int
).
Note
Note that in Python 2 a str
object with non-ASCII characters isoften not valid when a unicode string is expected. The mypy typesystem does not consider a string with non-ASCII values as aseparate type so some programs with this kind of error willsilently pass type checking. In Python 3 str
and bytes
areseparate, unrelated types and this kind of error is easy todetect. This a good reason for preferring Python 3 over Python 2!
See Text and AnyStr for details on how to enforce that avalue must be a unicode string in a cross-compatible way.