11.. _cheat-sheet-py3 :
22
3- Type hints cheat sheet (Python 3)
4- =================================
5-
6- This document is a quick cheat sheet showing how the :pep: `484 ` type
7- annotation notation represents various common types in Python 3.
8-
9- .. note ::
10-
11- Technically many of the type annotations shown below are redundant,
12- because mypy can derive them from the type of the expression. So
13- many of the examples have a dual purpose: show how to write the
14- annotation, and show the inferred types.
3+ Type hints cheat sheet
4+ ======================
155
6+ This document is a quick cheat sheet showing how to use type
7+ annotations for various common types in Python.
168
179Variables
1810*********
1911
20- Python 3.6 introduced a syntax for annotating variables in :pep: `526 `
21- and we use it in most examples.
12+ Technically many of the type annotations shown below are redundant,
13+ since mypy can usually infer the type of a variable from its value.
14+ See :ref: `type-inference-and-annotations ` for more details.
2215
2316.. code-block :: python
2417
25- # This is how you declare the type of a variable type in Python 3.6
18+ # This is how you declare the type of a variable
2619 age: int = 1
2720
2821 # You don't need to initialize a variable to annotate it
2922 a: int # Ok (no value at runtime until assigned)
3023
31- # The latter is useful in conditional branches
24+ # Doing so is useful in conditional branches
3225 child: bool
3326 if age < 18 :
3427 child = True
3528 else :
3629 child = False
3730
3831
39- Built -in types
40- **************
32+ Useful built -in types
33+ *********************
4134
4235.. code-block :: python
4336
44-
4537 from typing import List, Set, Dict, Tuple, Optional
4638
47- # For simple built-in types, just use the name of the type
39+ # For most types, just use the name of the type
4840 x: int = 1
4941 x: float = 1.0
5042 x: bool = True
@@ -85,8 +77,6 @@ Built-in types
8577 Functions
8678*********
8779
88- Python 3 supports an annotation syntax for function declarations.
89-
9080.. code-block :: python
9181
9282 from typing import Callable, Iterator, Union, Optional
@@ -124,73 +114,69 @@ Python 3 supports an annotation syntax for function declarations.
124114 ) -> bool :
125115 ...
126116
127- # An argument can be declared positional-only by giving it a name
128- # starting with two underscores:
129- def quux (__x : int ) -> None :
117+ # Mypy understands positional-only and keyword-only arguments
118+ # Positional-only arguments can also be marked by using a name starting with
119+ # two underscores
120+ def quux (x : int , / * , y : int ) -> None :
130121 pass
131122
132- quux(3 ) # Fine
133- quux(__x = 3 ) # Error
123+ quux(3 , y = 5 ) # Ok
124+ quux(3 , 5 ) # error: Too many positional arguments for "quux"
125+ quux(x = 3 , y = 5 ) # error: Unexpected keyword argument "x" for "quux"
126+
127+ # This makes each positional arg and each keyword arg a "str"
128+ def call (self , * args : str , ** kwargs : str ) -> str :
129+ reveal_type(args) # Revealed type is "tuple[str, ...]"
130+ reveal_type(kwargs) # Revealed type is "dict[str, str]"
131+ request = make_request(* args, ** kwargs)
132+ return self .do_api_query(request)
134133
135134 When you're puzzled or when things are complicated
136135**************************************************
137136
138137.. code-block :: python
139138
140- from typing import Union, Any, Optional, cast
139+ from typing import Union, Any, Optional, TYPE_CHECKING , cast
141140
142141 # To find out what type mypy infers for an expression anywhere in
143142 # your program, wrap it in reveal_type(). Mypy will print an error
144143 # message with the type; remove it again before running the code.
145- reveal_type(1 ) # -> Revealed type is "builtins.int"
144+ reveal_type(1 ) # Revealed type is "builtins.int"
146145
147146 # Use Union when something could be one of a few types
148147 x: list[Union[int , str ]] = [3 , 5 , " test" , " fun" ]
149148
150- # Use Any if you don't know the type of something or it's too
151- # dynamic to write a type for
152- x: Any = mystery_function()
153-
154149 # If you initialize a variable with an empty container or "None"
155- # you may have to help mypy a bit by providing a type annotation
150+ # you may have to help mypy a bit by providing an explicit type annotation
156151 x: list[str ] = []
157152 x: Optional[str ] = None
158153
159- # This makes each positional arg and each keyword arg a "str"
160- def call (self , * args : str , ** kwargs : str ) -> str :
161- request = make_request(* args, ** kwargs)
162- return self .do_api_query(request)
154+ # Use Any if you don't know the type of something or it's too
155+ # dynamic to write a type for
156+ x: Any = mystery_function()
163157
164158 # Use a "type: ignore" comment to suppress errors on a given line,
165159 # when your code confuses mypy or runs into an outright bug in mypy.
166- # Good practice is to comment every "ignore" with a bug link
167- # (in mypy, typeshed, or your own code) or an explanation of the issue.
168- x = confusing_function() # type: ignore # https://github.com/python/mypy/issues/1167
160+ # Good practice is to add a comment explaining the issue.
161+ x = confusing_function() # type: ignore # confusing_function won't return None here because ...
169162
170163 # "cast" is a helper function that lets you override the inferred
171164 # type of an expression. It's only for mypy -- there's no runtime check.
172165 a = [4 ]
173166 b = cast(list[int ], a) # Passes fine
174- c = cast(list[str ], a) # Passes fine (no runtime check)
175- reveal_type(c) # -> Revealed type is "builtins.list[builtins.str]"
176- print (c) # -> [4]; the object is not cast
177-
178- # If you want dynamic attributes on your class, have it override "__setattr__"
179- # or "__getattr__" in a stub or in your source code.
180- #
181- # "__setattr__" allows for dynamic assignment to names
182- # "__getattr__" allows for dynamic access to names
183- class A :
184- # This will allow assignment to any A.x, if x is the same type as "value"
185- # (use "value: Any" to allow arbitrary types)
186- def __setattr__ (self , name : str , value : int ) -> None : ...
187-
188- # This will allow access to any A.x, if x is compatible with the return type
189- def __getattr__ (self , name : str ) -> int : ...
190-
191- a.foo = 42 # Works
192- a.bar = ' Ex-parrot' # Fails type checking
167+ c = cast(list[str ], a) # Passes fine despite being a lie (no runtime check)
168+ reveal_type(c) # Revealed type is "builtins.list[builtins.str]"
169+ print (c) # Still prints [4] ... the object is not changed or casted at runtime
170+
171+ # Use "TYPE_CHECKING" if you want to have code that mypy can see but will not
172+ # be executed at runtime (or to have code that mypy can't see)
173+ if TYPE_CHECKING :
174+ import json
175+ else :
176+ import orjson as json # mypy is unaware of this
193177
178+ In some cases type annotations can cause issues at runtime, see
179+ :ref: `runtime_troubles ` for dealing with this.
194180
195181Standard "duck types"
196182*********************
@@ -216,7 +202,7 @@ that are common in idiomatic Python are standardized.
216202 # Mapping describes a dict-like object (with "__getitem__") that we won't
217203 # mutate, and MutableMapping one (with "__setitem__") that we might
218204 def f (my_mapping : Mapping[int , str ]) -> list[int ]:
219- my_mapping[5 ] = ' maybe' # if we try this, mypy will throw an error ...
205+ my_mapping[5 ] = ' maybe' # mypy will complain about this line ...
220206 return list (my_mapping.keys())
221207
222208 f({3 : ' yes' , 4 : ' no' })
@@ -263,6 +249,22 @@ Classes
263249 def __init__ (self ) -> None :
264250 self .items: list[str ] = []
265251
252+ # If you want dynamic attributes on your class, have it override "__setattr__"
253+ # or "__getattr__" in a stub or in your source code.
254+ #
255+ # "__setattr__" allows for dynamic assignment to names
256+ # "__getattr__" allows for dynamic access to names
257+ class A :
258+ # This will allow assignment to any A.x, if x is the same type as "value"
259+ # (use "value: Any" to allow arbitrary types)
260+ def __setattr__ (self , name : str , value : int ) -> None : ...
261+
262+ # This will allow access to any A.x, if x is compatible with the return type
263+ def __getattr__ (self , name : str ) -> int : ...
264+
265+ a.foo = 42 # Works
266+ a.bar = ' Ex-parrot' # Fails type checking
267+
266268
267269 Coroutines and asyncio
268270**********************
0 commit comments