Skip to content

Commit 10ae912

Browse files
Improvements to cheat sheet (#14972)
Everyone can use future annotations now. Also forward references are the most type hinting popular question on Stack Overflow, so give a little more detail. The IO example should go with standard duck types. I moved the async example to the bottom. It basically just works as you'd expect, maybe we should remove it altogether. Linking #13681 --------- Co-authored-by: Ethan Smith <[email protected]>
1 parent 7c49fa6 commit 10ae912

File tree

2 files changed

+53
-38
lines changed

2 files changed

+53
-38
lines changed

docs/source/cheat_sheet_py3.rst

+51-38
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ See :ref:`type-inference-and-annotations` for more details.
2121
# You don't need to initialize a variable to annotate it
2222
a: int # Ok (no value at runtime until assigned)
2323
24-
# Doing so is useful in conditional branches
24+
# Doing so can be useful in conditional branches
2525
child: bool
2626
if age < 18:
2727
child = True
@@ -34,7 +34,7 @@ Useful built-in types
3434

3535
.. code-block:: python
3636
37-
# For most types, just use the name of the type.
37+
# For most types, just use the name of the type in the annotation
3838
# Note that mypy can usually infer the type of a variable from its value,
3939
# so technically these annotations are redundant
4040
x: int = 1
@@ -75,10 +75,11 @@ Useful built-in types
7575
# Use Optional[X] for a value that could be None
7676
# Optional[X] is the same as X | None or Union[X, None]
7777
x: Optional[str] = "something" if some_condition() else None
78-
# Mypy understands a value can't be None in an if-statement
7978
if x is not None:
79+
# Mypy understands x won't be None here because of the if-statement
8080
print(x.upper())
81-
# If a value can never be None due to some invariants, use an assert
81+
# If you know a value can never be None due to some logic that mypy doesn't
82+
# understand, use an assert
8283
assert x is not None
8384
print(x.upper())
8485
@@ -259,6 +260,8 @@ When you're puzzled or when things are complicated
259260
In some cases type annotations can cause issues at runtime, see
260261
:ref:`runtime_troubles` for dealing with this.
261262

263+
See :ref:`silencing-type-errors` for details on how to silence errors.
264+
262265
Standard "duck types"
263266
*********************
264267

@@ -294,37 +297,11 @@ that are common in idiomatic Python are standardized.
294297
295298
f({3: 'yes', 4: 'no'})
296299
297-
298-
You can even make your own duck types using :ref:`protocol-types`.
299-
300-
Coroutines and asyncio
301-
**********************
302-
303-
See :ref:`async-and-await` for the full detail on typing coroutines and asynchronous code.
304-
305-
.. code-block:: python
306-
307-
import asyncio
308-
309-
# A coroutine is typed like a normal function
310-
async def countdown35(tag: str, count: int) -> str:
311-
while count > 0:
312-
print(f'T-minus {count} ({tag})')
313-
await asyncio.sleep(0.1)
314-
count -= 1
315-
return "Blastoff!"
316-
317-
318-
Miscellaneous
319-
*************
320-
321-
.. code-block:: python
322-
323300
import sys
324301
from typing import IO
325302
326-
# Use IO[] for functions that should accept or return any
327-
# object that comes from an open() call (IO[] does not
303+
# Use IO[str] or IO[bytes] for functions that should accept or return
304+
# objects that come from an open() call (note that IO does not
328305
# distinguish between reading, writing or other modes)
329306
def get_sys_IO(mode: str = 'w') -> IO[str]:
330307
if mode == 'w':
@@ -334,19 +311,38 @@ Miscellaneous
334311
else:
335312
return sys.stdout
336313
337-
# Forward references are useful if you want to reference a class before
338-
# it is defined
314+
315+
You can even make your own duck types using :ref:`protocol-types`.
316+
317+
Forward references
318+
******************
319+
320+
.. code-block:: python
321+
322+
# You may want to reference a class before it is defined.
323+
# This is known as a "forward reference".
339324
def f(foo: A) -> int: # This will fail at runtime with 'A' is not defined
340325
...
341326
342-
class A:
327+
# However, if you add the following special import:
328+
from __future__ import annotations
329+
# It will work at runtime and type checking will succeed as long as there
330+
# is a class of that name later on in the file
331+
def f(foo: A) -> int: # Ok
343332
...
344333
345-
# If you use the string literal 'A', it will pass as long as there is a
346-
# class of that name later on in the file
347-
def f(foo: 'A') -> int: # Ok
334+
# Another option is to just put the type in quotes
335+
def f(foo: 'A') -> int: # Also ok
348336
...
349337
338+
class A:
339+
# This can also come up if you need to reference a class in a type
340+
# annotation inside the definition of that class
341+
@classmethod
342+
def create(cls) -> A:
343+
...
344+
345+
See :ref:`forward-references` for more details.
350346

351347
Decorators
352348
**********
@@ -365,3 +361,20 @@ Decorator functions can be expressed via generics. See
365361
366362
def decorator_args(url: str) -> Callable[[F], F]:
367363
...
364+
365+
Coroutines and asyncio
366+
**********************
367+
368+
See :ref:`async-and-await` for the full detail on typing coroutines and asynchronous code.
369+
370+
.. code-block:: python
371+
372+
import asyncio
373+
374+
# A coroutine is typed like a normal function
375+
async def countdown(tag: str, count: int) -> str:
376+
while count > 0:
377+
print(f'T-minus {count} ({tag})')
378+
await asyncio.sleep(0.1)
379+
count -= 1
380+
return "Blastoff!"

docs/source/runtime_troubles.rst

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ Since code inside ``if TYPE_CHECKING:`` is not executed at runtime, it provides
117117
a convenient way to tell mypy something without the code being evaluated at
118118
runtime. This is most useful for resolving :ref:`import cycles <import-cycles>`.
119119

120+
.. _forward-references:
121+
120122
Class name forward references
121123
-----------------------------
122124

0 commit comments

Comments
 (0)