-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Expand "getting started" docs to discuss type hints in more detail #6226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This pull request expands our "getting started" docs so they discuss how to use type hints in more detail. In general, I'm hoping this pull request will accomplish two main things: 1. Give users a better "tour" of the available PEP 484 types. 2. Do a better job of giving users a "heads-up" of common gotchas: for example, how dynamically typed functions aren't type-checked. Here's a list of specific changes I made: 1. I combined "Installing mypy" and "Running mypy" into one section. 2. I modified the "Function signatures" section to focus more on the distinction between dynamic and static typing: I suspect that's a common tripup new users run into. I also changed the examples so they'll actually produce a runtime error if you misuse them. 3. I moved the existing text on annotating no-argument functions or functions with default arguments into a separate "More function signatures" to try and keep the new "Function signatures and and dynamic vs static typing" section focused. 4. I expanded the section about using the "typing" module to be more thorough. In particular, I wanted to expose the user to the concept of concrete generic types (List), abstract generic types/protocols (Iterable), and to more non-conventional types like Union. I think these three examples are broadly representative of the different "flavors" of PEP 484 types and so should help new users be a little more aware of the kinds of things they can do with types. The main thing that's missing is an introduction to custom generic classes and functions: that's probably too complex of a topic to belong in this page. 5. I added a section on local type inference: it's a new concept for people who are more used to languages like Java or C# so felt like it was worth mentioning. This section also covers the final stumbling block I think new users are likely to run into: the "Need type annotation for 'variable'" error message. 6. I added a section on customizing mypy via the command line flags. I don't think enough users are aware that you can do this, despite how useful the flags can be.
| generic types) by looking through the | ||
| :ref:`type system reference <overview-type-system-reference>`. | ||
|
|
||
| One final note: when adding types, the convention is to import types |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it also fair to say that it is conventional to put typing imports as the first imports? (It seems like it to me, at least).
If it's not actually a common convention, then it shouldn't derail this PR, but if it is I think it will be nice to mention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also personally like that style (and I think mypy itself also follows that convention), but I'm thinking it's probably best to not mention this for now -- I'm not sure if other Python linters have caught up on this convention yet. For example, I think isort will sort imports alphabetically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong preference, but I also like typing imports first. isort however has a different opinion (maybe it is configurable, I have very little experience with it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that this convention is followed very widely. The mypy implementation doesn't consistently put typing imports first. I would rather not recommend any particular placement for the imports.
Co-Authored-By: Michael0x2a <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for improving our docs! This should make it easier for new users to get started. Left a bunch of mostly minor comments.
docs/source/getting_started.rst
Outdated
| def f(): | ||
| 1 + 'x' # No static type error (dynamically typed) | ||
| def stars(*names: str, **kwargs: float) -> float: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this example is a bit too clever. Maybe instead write too simpler (unrelated) functions, one for demonstrating *args and the other for **kwargs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided to just give up on trying to come up with a motivated example in this case and just left in comments describing what types 'args' and 'kwargs' would have.
| generic types) by looking through the | ||
| :ref:`type system reference <overview-type-system-reference>`. | ||
|
|
||
| One final note: when adding types, the convention is to import types |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that this convention is followed very widely. The mypy implementation doesn't consistently put typing imports first. I would rather not recommend any particular placement for the imports.
docs/source/getting_started.rst
Outdated
| add a dynamically-typed function by mistake. You can make mypy do this | ||
| by running mypy with the ``--disallow-untyped-defs`` flag. | ||
|
|
||
| One particularly useful command is the ``--strict`` flag. Running |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we should recommend --strict here. Even mypy doesn't use all the options it enables yet. At least I think that there is too much emphasis on it now. I think it might be okay to mention it here as option for people who want to go the extra mile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I decreased the emphasis a bit -- let me know if you want me to go even further.
|
Two more things:
|
- Fix small suggestions made - Simplify the `*args` and `**kwargs` example (or rather, just give up on constructing an example altogether) - Sneak in an example of `Tuple[...]` when discussing `*args` - Discuss `Optional[...]` -- and also sneak in an example of mypy understanding `x is None` checks.
|
@ilevkivskyi and @JukkaL -- ok, this should be ready for a second look whenever! @JukkaL -- I added in a section about Optional types, as suggested. I also tried adding in some discussion of Tuple, but everything I tried adding felt a little bloated. I think as a compromise, what I'll do is submit a follow-up diff where I expand the "built-in types" page and have the "getting started" page directly link to that. |
docs/source/getting_started.rst
Outdated
| .. code-block:: python | ||
| # If you are using Python 3.6+, you can use variable annotations. | ||
| # See https://www.python.org/dev/peps/pep-0526/ for more on variable annotations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a clickable link would look better. For example, ...we could `annotate <pep526_>`_ it... in the text above. Or maybe just abandon this idea, in any case non-clickable links look bad in the docs.
Also I thought most of the documentation uses "you could..." style, but you have couple of "we" in that sentence above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates! Looks good to me now, just one minor comment.
docs/source/getting_started.rst
Outdated
| print('Hello, {}'.format(name)) | ||
| print('Hello ' + name) | ||
| As a final example, suppose want to write a function that can accept *either* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this is no longer the final example.
This pull request expands our "getting started" docs so they discuss how to use type hints in more detail.
In general, I'm hoping this pull request will accomplish two main things:
Give users a better "tour" of the available PEP 484 types.
Do a better job of giving users a "heads-up" of common gotchas: for example, how dynamically typed functions aren't type-checked.
Here's a list of specific changes I made:
I combined "Installing mypy" and "Running mypy" into one section.
I modified the "Function signatures" section to focus more on the distinction between dynamic and static typing: I suspect that's a common tripup new users run into.
I also changed the examples so they'll actually produce a runtime error if you misuse them.
I moved the existing text on annotating no-argument functions or functions with default arguments into a separate "More function signatures" to try and keep the new "Function signatures and dynamic vs static typing" section focused.
I expanded the section about using the "typing" module to be more thorough. In particular, I wanted to expose the user to the concept of concrete generic types (List), abstract generic types/protocols (Iterable), and to more non-conventional types like Union.
I think these three examples are broadly representative of the different "flavors" of PEP 484 types and so should help new users be a little more aware of the kinds of things they can do with types.
The main thing that's missing is an introduction to custom generic classes and functions: that's probably too complex of a topic to belong in this page.
I added a section on local type inference: it's a new concept for people who are more used to languages like Java or C# so felt like it was worth mentioning.
This section also covers the other stumbling block I think new users are likely to run into: the "Need type annotation for 'variable'" error message.
I added a section on customizing mypy via the command line flags. I don't think enough users are aware that you can do this, despite how useful the flags can be.