@@ -6,19 +6,30 @@ Type inference and type annotations
6
6
Type inference
7
7
**************
8
8
9
- Mypy considers the initial assignment as the definition of a variable.
10
- If you do not explicitly
11
- specify the type of the variable, mypy infers the type based on the
12
- static type of the value expression:
9
+ For most variables, if you do not explicitly specify its type, mypy will
10
+ infer the correct type based on what is initially assigned to the variable.
13
11
14
12
.. code-block :: python
15
13
16
- i = 1 # Infer type "int" for i
17
- l = [1 , 2 ] # Infer type "list[int]" for l
14
+ # Mypy will infer the type of these variables, despite no annotations
15
+ i = 1
16
+ reveal_type(i) # Revealed type is "builtins.int"
17
+ l = [1 , 2 ]
18
+ reveal_type(l) # Revealed type is "builtins.list[builtins.int]"
18
19
19
- Type inference is not used in dynamically typed functions (those
20
- without a function type annotation) — every local variable type defaults
21
- to ``Any `` in such functions. ``Any `` is discussed later in more detail.
20
+
21
+ .. note ::
22
+
23
+ Note that mypy will not use type inference in dynamically typed functions
24
+ (those without a function type annotation) — every local variable type
25
+ defaults to ``Any `` in such functions. For more details, see :ref: `dynamic-typing `.
26
+
27
+ .. code-block :: python
28
+
29
+ def untyped_function ():
30
+ i = 1
31
+ reveal_type(i) # Revealed type is "Any"
32
+ # 'reveal_type' always outputs 'Any' in unchecked functions
22
33
23
34
.. _explicit-var-types :
24
35
@@ -37,20 +48,33 @@ variable type annotation:
37
48
Without the type annotation, the type of ``x `` would be just ``int ``. We
38
49
use an annotation to give it a more general type ``Union[int, str] `` (this
39
50
type means that the value can be either an ``int `` or a ``str ``).
40
- Mypy checks that the type of the initializer is compatible with the
41
- declared type. The following example is not valid, since the initializer is
42
- a floating point number, and this is incompatible with the declared
43
- type :
51
+
52
+ The best way to think about this is that the type annotation sets the type of
53
+ the variable, not the type of the expression. For instance, mypy will complain
54
+ about the following code :
44
55
45
56
.. code-block :: python
46
57
47
- x: Union[int , str ] = 1.1 # Error!
58
+ x: Union[int , str ] = 1.1 # error: Incompatible types in assignment
59
+ # (expression has type "float", variable has type "Union[int, str]")
48
60
49
61
.. note ::
50
62
51
- The best way to think about this is that the type annotation sets the
52
- type of the variable, not the type of the expression. To force the
53
- type of an expression you can use :py:func: `cast(\< type\> , \< expression\> ) <typing.cast> `.
63
+ To explicitly override the type of an expression you can use
64
+ :py:func: `cast(\< type\> , \< expression\> ) <typing.cast> `.
65
+ See :ref: `casts ` for details.
66
+
67
+ Note that you can explicitly declare the type of a variable without
68
+ giving it an initial value:
69
+
70
+ .. code-block :: python
71
+
72
+ # We only unpack two values, so there's no right-hand side value
73
+ # for mypy to infer the type of "cs" from:
74
+ a, b, * cs = 1 , 2 # error: Need type annotation for "cs"
75
+
76
+ rs: list[int ] # no assignment!
77
+ p, q, * rs = 1 , 2 # OK
54
78
55
79
Explicit types for collections
56
80
******************************
@@ -69,15 +93,9 @@ In these cases you can give the type explicitly using a type annotation:
69
93
70
94
.. code-block :: python
71
95
72
- l: list[int ] = [] # Create empty list with type list[ int]
96
+ l: list[int ] = [] # Create empty list of int
73
97
d: dict[str , int ] = {} # Create empty dictionary (str -> int)
74
98
75
- Similarly, you can also give an explicit type when creating an empty set:
76
-
77
- .. code-block :: python
78
-
79
- s: set[int ] = set ()
80
-
81
99
.. note ::
82
100
83
101
Using type arguments (e.g. ``list[int] ``) on builtin collections like
@@ -90,13 +108,14 @@ Similarly, you can also give an explicit type when creating an empty set:
90
108
Compatibility of container types
91
109
********************************
92
110
93
- The following program generates a mypy error, since ``list[int] ``
94
- is not compatible with ``list[object] ``:
111
+ A quick note: container types can sometimes be unintuitive. We'll discuss this
112
+ more in :ref: `variance `. For example, the following program generates a mypy error,
113
+ because mypy treats ``list[int] `` as incompatible with ``list[object] ``:
95
114
96
115
.. code-block :: python
97
116
98
117
def f (l : list[object ], k : list[int ]) -> None :
99
- l = k # Type check error: incompatible types in assignment
118
+ l = k # error: Incompatible types in assignment
100
119
101
120
The reason why the above assignment is disallowed is that allowing the
102
121
assignment could result in non-int values stored in a list of ``int ``:
@@ -108,33 +127,32 @@ assignment could result in non-int values stored in a list of ``int``:
108
127
l.append(' x' )
109
128
print (k[- 1 ]) # Ouch; a string in list[int]
110
129
111
- Other container types like :py:class: `dict ` and :py:class: `set ` behave similarly. We
112
- will discuss how you can work around this in :ref: `variance `.
130
+ Other container types like :py:class: `dict ` and :py:class: `set ` behave similarly.
113
131
114
- You can still run the above program; it prints ``x ``. This illustrates
115
- the fact that static types are used during type checking, but they do
116
- not affect the runtime behavior of programs. You can run programs with
117
- type check failures, which is often very handy when performing a large
118
- refactoring. Thus you can always 'work around' the type system, and it
132
+ You can still run the above program; it prints ``x ``. This illustrates the fact
133
+ that static types do not affect the runtime behavior of programs. You can run
134
+ programs with type check failures, which is often very handy when performing a
135
+ large refactoring. Thus you can always 'work around' the type system, and it
119
136
doesn't really limit what you can do in your program.
120
137
121
138
Context in type inference
122
139
*************************
123
140
124
- Type inference is *bidirectional * and takes context into account. For
125
- example, the following is valid:
141
+ Type inference is *bidirectional * and takes context into account.
142
+
143
+ Mypy will take into account the type of the variable on the left-hand side
144
+ of an assignment when inferring the type of the expression on the right-hand
145
+ side. For example, the following will type check:
126
146
127
147
.. code-block :: python
128
148
129
149
def f (l : list[object ]) -> None :
130
150
l = [1 , 2 ] # Infer type list[object] for [1, 2], not list[int]
131
151
132
- In an assignment, the type context is determined by the assignment
133
- target. In this case this is ``l ``, which has the type
134
- ``list[object] ``. The value expression ``[1, 2] `` is type checked in
135
- this context and given the type ``list[object] ``. In the previous
136
- example we introduced a new variable ``l ``, and here the type context
137
- was empty.
152
+
153
+ The value expression ``[1, 2] `` is type checked with the additional
154
+ context that it is being assigned to a variable of type ``list[object] ``.
155
+ This is used to infer the type of the *expression * as ``list[object] ``.
138
156
139
157
Declared argument types are also used for type context. In this program
140
158
mypy knows that the empty list ``[] `` should have type ``list[int] `` based
@@ -167,51 +185,30 @@ Working around the issue is easy by adding a type annotation:
167
185
a: list[int ] = [] # OK
168
186
foo(a)
169
187
170
- Starred expressions
171
- *******************
172
-
173
- In most cases, mypy can infer the type of starred expressions from the
174
- right-hand side of an assignment, but not always:
175
-
176
- .. code-block :: python
177
-
178
- a, * bs = 1 , 2 , 3 # OK
179
- p, q, * rs = 1 , 2 # Error: Type of rs cannot be inferred
180
-
181
- On first line, the type of ``bs `` is inferred to be
182
- ``list[int] ``. However, on the second line, mypy cannot infer the type
183
- of ``rs ``, because there is no right-hand side value for ``rs `` to
184
- infer the type from. In cases like these, the starred expression needs
185
- to be annotated with a starred type:
186
-
187
- .. code-block :: python
188
-
189
- p, q, * rs = 1 , 2 # type: int , int , list [ int ]
190
-
191
- Here, the type of ``rs `` is set to ``list[int] ``.
192
-
193
188
Silencing type errors
194
189
*********************
195
190
196
191
You might want to disable type checking on specific lines, or within specific
197
192
files in your codebase. To do that, you can use a ``# type: ignore `` comment.
198
193
199
- For example, say that the web framework that you use now takes an integer
200
- argument to ``run() ``, which starts it on localhost on that port. Like so:
194
+ For example, say in its latest update, the web framework you use can now take an
195
+ integer argument to ``run() ``, which starts it on localhost on that port.
196
+ Like so:
201
197
202
198
.. code-block :: python
203
199
204
200
# Starting app on http://localhost:8000
205
201
app.run(8000 )
206
202
207
- However, the type stubs that the package uses is not up-to-date, and it still
208
- expects only ``str `` types for ``run() ``. This would give you the following error:
203
+ However, the devs forgot to update their type annotations for
204
+ ``run ``, so mypy still thinks ``run `` only expects ``str `` types.
205
+ This would give you the following error:
209
206
210
207
.. code-block :: text
211
208
212
209
error: Argument 1 to "run" of "A" has incompatible type "int"; expected "str"
213
210
214
- If you cannot directly fix the type stubs yourself, you can temporarily
211
+ If you cannot directly fix the web framework yourself, you can temporarily
215
212
disable type checking on that line, by adding a ``# type: ignore ``:
216
213
217
214
.. code-block :: python
@@ -229,7 +226,7 @@ short explanation of the bug. To do that, use this format:
229
226
.. code-block :: python
230
227
231
228
# Starting app on http://localhost:8000
232
- app.run(8000 ) # type: ignore # `run()` now accepts an `int`, as a port
229
+ app.run(8000 ) # type: ignore # `run()` in v2.0 accepts an `int`, as a port
233
230
234
231
235
232
Mypy displays an error code for each error if you use
@@ -244,12 +241,12 @@ It is possible to add a specific error-code in your ignore comment (e.g.
244
241
``# type: ignore[attr-defined] ``) to clarify what's being silenced. You can
245
242
find more information about error codes :ref: `here <silence-error-codes >`.
246
243
247
- Similarly, you can also ignore all mypy checks in a file, by adding a
248
- ``# type : ignore `` at the top of the file:
244
+ Similarly, you can also ignore all mypy errors in a file, by adding a
245
+ ``# mypy : ignore-errors `` at the top of the file:
249
246
250
247
.. code-block :: python
251
248
252
- # type : ignore
249
+ # mypy : ignore-errors
253
250
# This is a test file, skipping type checking in it.
254
251
import unittest
255
252
...
0 commit comments