4
4
Dynamically typed code
5
5
======================
6
6
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).
13
17
14
18
.. code-block :: python
15
19
16
20
from typing import Any
17
21
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.
22
34
23
35
Operations on Any values
24
36
------------------------
25
37
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:
28
40
29
41
.. code-block :: python
30
42
@@ -37,20 +49,53 @@ does not complain:
37
49
open (x).read()
38
50
return x
39
51
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 ``
41
53
implicitly, as mypy can't infer a more precise result type. For
42
54
example, if you get the attribute of an ``Any `` value or call a
43
55
``Any `` value the result is ``Any ``:
44
56
45
57
.. code-block :: python
46
58
47
59
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"
50
64
51
65
``Any `` types may propagate through your program, making type checking
52
66
less effective, unless you are careful.
53
67
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
+
54
99
Any vs. object
55
100
--------------
56
101
@@ -80,6 +125,11 @@ operations:
80
125
n: int = 1
81
126
n = o # Error!
82
127
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
+
83
133
You can use different :ref: `type narrowing <type-narrowing >`
84
134
techniques to narrow :py:class: `object ` to a more specific
85
135
type (subtype) such as ``int ``. Type narrowing is not needed with
0 commit comments