.. _dynamic-typing: Dynamically typed code ====================== In :ref:`getting-started-dynamic-vs-static`, we discussed how bodies of functions that don't have any explicit type annotations in their function are "dynamically typed" and that mypy will not check them. In this section, we'll talk a little bit more about what that means and how you can enable dynamic typing on a more fine grained basis. In cases where your code is too magical for mypy to understand, you can make a variable or parameter dynamically typed by explicitly giving it the type ``Any``. Mypy will let you do basically anything with a value of type ``Any``, including assigning a value of type ``Any`` to a variable of any type (or vice versa). .. code-block:: python from typing import Any num = 1 # Statically typed (inferred to be int) num = 'x' # error: Incompatible types in assignment (expression has type "str", variable has type "int") dyn: Any = 1 # Dynamically typed (type Any) dyn = 'x' # OK num = dyn # No error, mypy will let you assign a value of type Any to any variable num += 1 # Oops, mypy still thinks num is an int You can think of ``Any`` as a way to locally disable type checking. See :ref:`silencing-type-errors` for other ways you can shut up the type checker. Operations on Any values ------------------------ You can do anything using a value with type ``Any``, and the type checker will not complain: .. code-block:: python def f(x: Any) -> int: # All of these are valid! x.foobar(1, y=2) print(x[3] + 'f') if x: x.z = x(2) open(x).read() return x Values derived from an ``Any`` value also usually have the type ``Any`` implicitly, as mypy can't infer a more precise result type. For example, if you get the attribute of an ``Any`` value or call a ``Any`` value the result is ``Any``: .. code-block:: python def f(x: Any) -> None: y = x.foo() reveal_type(y) # Revealed type is "Any" z = y.bar("mypy will let you do anything to y") reveal_type(z) # Revealed type is "Any" ``Any`` types may propagate through your program, making type checking less effective, unless you are careful. Function parameters without annotations are also implicitly ``Any``: .. code-block:: python def f(x) -> None: reveal_type(x) # Revealed type is "Any" x.can.do["anything", x]("wants", 2) You can make mypy warn you about untyped function parameters using the :option:`--disallow-untyped-defs ` flag. Generic types missing type parameters will have those parameters implicitly treated as ``Any``: .. code-block:: python from typing import List def f(x: List) -> None: reveal_type(x) # Revealed type is "builtins.list[Any]" reveal_type(x[0]) # Revealed type is "Any" x[0].anything_goes() # OK You can make mypy warn you about untyped function parameters using the :option:`--disallow-any-generics ` flag. Finally, another major source of ``Any`` types leaking into your program is from third party libraries that mypy does not know about. This is particularly the case when using the :option:`--ignore-missing-imports ` flag. See :ref:`fix-missing-imports` for more information about this. Any vs. object -------------- The type :py:class:`object` is another type that can have an instance of arbitrary type as a value. Unlike ``Any``, :py:class:`object` is an ordinary static type (it is similar to ``Object`` in Java), and only operations valid for *all* types are accepted for :py:class:`object` values. These are all valid: .. code-block:: python def f(o: object) -> None: if o: print(o) print(isinstance(o, int)) o = 2 o = 'foo' These are, however, flagged as errors, since not all objects support these operations: .. code-block:: python def f(o: object) -> None: o.foo() # Error! o + 2 # Error! open(o) # Error! n: int = 1 n = o # Error! If you're not sure whether you need to use :py:class:`object` or ``Any``, use :py:class:`object` -- only switch to using ``Any`` if you get a type checker complaint. You can use different :ref:`type narrowing ` techniques to narrow :py:class:`object` to a more specific type (subtype) such as ``int``. Type narrowing is not needed with dynamically typed values (values with type ``Any``).