44Dynamically typed code
55======================
66
7- As mentioned earlier, bodies of functions that don't have any explicit
8- types in their function annotation are dynamically typed (operations
9- are checked at runtime). Code outside functions is statically typed by
10- default, and types of variables are inferred. This does usually the
11- right thing, but you can also make any variable dynamically typed by
12- defining it explicitly with the type ``Any ``:
7+ In :ref: `getting-started-dynamic-vs-static `, we discussed how bodies of functions
8+ that don't have any explicit type annotations in their function are "dynamically typed"
9+ and that mypy will not check them. In this section, we'll talk a little bit more
10+ about what that means and how you can enable dynamic typing on a more fine grained basis.
11+
12+ In cases where your code is too magical for mypy to understand, you can make a
13+ variable or parameter dynamically typed by explicitly giving it the type
14+ ``Any ``. Mypy will let you do basically anything with a value of type ``Any ``,
15+ including assigning a value of type ``Any `` to a variable of any type (or vice
16+ versa).
1317
1418.. code-block :: python
1519
1620 from typing import Any
1721
18- s = 1 # Statically typed (type int)
19- d: Any = 1 # Dynamically typed (type Any)
20- s = ' x' # Type check error
21- d = ' x' # OK
22+ num = 1 # Statically typed (inferred to be int)
23+ num = ' x' # error: Incompatible types in assignment (expression has type "str", variable has type "int")
24+
25+ dyn: Any = 1 # Dynamically typed (type Any)
26+ dyn = ' x' # OK
27+
28+ num = dyn # No error, mypy will let you assign a value of type Any to any variable
29+ num += 1 # Oops, mypy still thinks num is an int
30+
31+ You can think of ``Any `` as a way to locally disable type checking.
32+ See :ref: `silencing-type-errors ` for other ways you can shut up
33+ the type checker.
2234
2335Operations on Any values
2436------------------------
2537
26- You can do anything using a value with type ``Any ``, and type checker
27- does not complain:
38+ You can do anything using a value with type ``Any ``, and the type checker
39+ will not complain:
2840
2941.. code-block :: python
3042
@@ -37,20 +49,53 @@ does not complain:
3749 open (x).read()
3850 return x
3951
40- Values derived from an ``Any `` value also often have the type ``Any ``
52+ Values derived from an ``Any `` value also usually have the type ``Any ``
4153implicitly, as mypy can't infer a more precise result type. For
4254example, if you get the attribute of an ``Any `` value or call a
4355``Any `` value the result is ``Any ``:
4456
4557.. code-block :: python
4658
4759 def f (x : Any) -> None :
48- y = x.foo() # y has type Any
49- y.bar() # Okay as well!
60+ y = x.foo()
61+ reveal_type(y) # Revealed type is "Any"
62+ z = y.bar(" mypy will let you do anything to y" )
63+ reveal_type(z) # Revealed type is "Any"
5064
5165 ``Any `` types may propagate through your program, making type checking
5266less effective, unless you are careful.
5367
68+ Function parameters without annotations are also implicitly ``Any ``:
69+
70+ .. code-block :: python
71+
72+ def f (x ) -> None :
73+ reveal_type(x) # Revealed type is "Any"
74+ x.can.do[" anything" , x](" wants" , 2 )
75+
76+ You can make mypy warn you about untyped function parameters using the
77+ :option: `--disallow-untyped-defs <mypy --disallow-untyped-defs> ` flag.
78+
79+ Generic types missing type parameters will have those parameters implicitly
80+ treated as ``Any ``:
81+
82+ .. code-block :: python
83+
84+ from typing import List
85+
86+ def f (x : List) -> None :
87+ reveal_type(x) # Revealed type is "builtins.list[Any]"
88+ reveal_type(x[0 ]) # Revealed type is "Any"
89+ x[0 ].anything_goes() # OK
90+
91+ You can make mypy warn you about untyped function parameters using the
92+ :option: `--disallow-any-generics <mypy --disallow-any-generics> ` flag.
93+
94+ Finally, another major source of ``Any `` types leaking into your program is from
95+ third party libraries that mypy does not know about. This is particularly the case
96+ when using the :option: `--ignore-missing-imports <mypy --ignore-missing-imports> `
97+ flag. See :ref: `fix-missing-imports ` for more information about this.
98+
5499Any vs. object
55100--------------
56101
@@ -80,6 +125,11 @@ operations:
80125 n: int = 1
81126 n = o # Error!
82127
128+
129+ If you're not sure whether you need to use :py:class: `object ` or ``Any ``, use
130+ :py:class: `object ` -- only switch to using ``Any `` if you get a type checker
131+ complaint.
132+
83133You can use different :ref: `type narrowing <type-narrowing >`
84134techniques to narrow :py:class: `object ` to a more specific
85135type (subtype) such as ``int ``. Type narrowing is not needed with
0 commit comments