File: duck_type_compatibility.rst

package info (click to toggle)
mypy 0.812-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 18,596 kB
  • sloc: python: 74,869; cpp: 11,212; ansic: 3,935; makefile: 238; sh: 13
file content (45 lines) | stat: -rw-r--r-- 1,932 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Duck type compatibility
-----------------------

In Python, certain types are compatible even though they aren't subclasses of
each other. For example, ``int`` objects are valid whenever ``float`` objects
are expected. Mypy supports this idiom via *duck type compatibility*. This is
supported for a small set of built-in types:

* ``int`` is duck type compatible with ``float`` and ``complex``.
* ``float`` is duck type compatible with ``complex``.
* ``bytearray`` and ``memoryview`` are duck type compatible with ``bytes``.
* In Python 2, ``str`` is duck type compatible with ``unicode``.

For example, mypy considers an ``int`` object to be valid whenever a
``float`` object is expected.  Thus code like this is nice and clean
and also behaves as expected:

.. code-block:: python

   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 :ref:`protocol-types` to achieve a similar effect in
a more principled and extensible fashion. Protocols don't apply to
cases like ``int`` being compatible with ``float``, since ``float`` is not
a protocol class but a regular, concrete class, and many standard library
functions expect concrete instances of ``float`` (or ``int``).

.. note::

   Note that in Python 2 a ``str`` object with non-ASCII characters is
   often *not valid* when a unicode string is expected. The mypy type
   system does not consider a string with non-ASCII values as a
   separate type so some programs with this kind of error will
   silently pass type checking. In Python 3 ``str`` and ``bytes`` are
   separate, unrelated types and this kind of error is easy to
   detect. This a good reason for preferring Python 3 over Python 2!

   See :ref:`text-and-anystr` for details on how to enforce that a
   value must be a unicode string in a cross-compatible way.